-
Notifications
You must be signed in to change notification settings - Fork 68
/
CogObjectRepresentationFor64BitSpur.class.st
2363 lines (2159 loc) · 100 KB
/
CogObjectRepresentationFor64BitSpur.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 : #CogObjectRepresentationFor64BitSpur,
#superclass : #CogObjectRepresentationForSpur,
#instVars : [
'ceDereferenceSelectorIndex'
],
#category : #'VMMaker-JIT'
}
{ #category : #'accessing class hierarchy' }
CogObjectRepresentationFor64BitSpur class >> defaultObjectMemoryClass [
"For in-image compilation. Spur64BitCoMemoryManager is as yet undefined."
^Smalltalk classNamed: #Spur64BitCoMemoryManager
]
{ #category : #accessing }
CogObjectRepresentationFor64BitSpur class >> wordSize [
^8
]
{ #category : #'sista support' }
CogObjectRepresentationFor64BitSpur >> allImmediate: immediateMask branchIf: reg instanceOfBehaviors: arrayObj target: targetFixUp [
| tag1 tag2 |
<var: #targetFixUp type: #'AbstractInstruction *'>
immediateMask = objectMemory tagMask ifTrue: [(self genJumpImmediate: reg) jmpTarget: targetFixUp. ^0].
"TempReg holds the rcvr tag"
"In this case one immediate tag out of the three is not present in arrayObj."
tag1 := objectMemory classTagForClass: (objectMemory fetchPointer: 0 ofObject: arrayObj).
tag2 := objectMemory classTagForClass: (objectMemory fetchPointer: 1 ofObject: arrayObj).
(tag1 = objectMemory smallIntegerTag or: [tag2 = objectMemory smallIntegerTag]) ifTrue:
[(self genJumpSmallIntegerInScratchReg: TempReg) jmpTarget: targetFixUp].
(tag1 = objectMemory characterTag or: [tag2 = objectMemory characterTag]) ifTrue:
[(self genJumpCharacterInScratchReg: TempReg) jmpTarget: targetFixUp].
(tag1 = objectMemory smallFloatTag or: [tag2 = objectMemory smallFloatTag]) ifTrue:
[(self genJumpSmallFloatInScratchReg: TempReg) jmpTarget: targetFixUp].
^0
]
{ #category : #'sista support' }
CogObjectRepresentationFor64BitSpur >> allImmediate: immediateMask branchIf: reg notInstanceOfBehaviors: arrayObj target: targetFixUp [
| incorrectTag tag1 tag2 |
<var: #targetFixUp type: #'AbstractInstruction *'>
(self genJumpNotImmediate: reg) jmpTarget: targetFixUp.
immediateMask = objectMemory tagMask ifFalse:
[ "TempReg holds the rcvr tag"
"In this case one immediate tag out of the three is not present in arrayObj.
We look for it, and generate a jump to the fixup if the rcvr tag matches"
tag1 := objectMemory classTagForClass: (objectMemory fetchPointer: 0 ofObject: arrayObj).
tag2 := objectMemory classTagForClass: (objectMemory fetchPointer: 1 ofObject: arrayObj).
incorrectTag := self fetchImmediateTagOtherThanTag1: tag1 tag2: tag2.
cogit CmpCq: incorrectTag R: TempReg.
cogit JumpZero: targetFixUp].
^0
]
{ #category : #'sista support' }
CogObjectRepresentationFor64BitSpur >> 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 + 1 // 2.
^objOop
ifNil: [0]
ifNotNil: [objOop + objectMemory baseHeaderSize]
]
{ #category : #'in-line cacheing' }
CogObjectRepresentationFor64BitSpur >> bitAndByteOffsetOfIsFullBlockBitInto: aBlock [
<inline: true>
"This supplies the bitmask for the isFullBlock bit, and the offset of the byte containing
that bit in a CogMethod header to aBlock. We don't have named variables holding this
offset. The following assert tests whether the values are correct by creating a surrogate
on an empty ByteArray, setting the bit, and checking that the expected values are set
in the ByteArray."
self cCode: [] inSmalltalk:
[| m |
m := ByteArray new: 16.
CogBlockMethodSurrogate64 new
at: 0 memory: m headerSize: 8 cogit: nil;
cpicHasMNUCaseOrCMIsFullBlock: true.
self assert: m = #[0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 0].
self assert: (m at: objectMemory baseHeaderSize + 2) = 16].
aBlock value: 16 value: objectMemory baseHeaderSize + 1 "zero-relative"
]
{ #category : #'sista support' }
CogObjectRepresentationFor64BitSpur >> branch2CasesIf: reg instanceOfBehaviors: arrayObj target: targetFixUp [
| classObj tag1 tag2 |
< inline: true>
"look for the 2 tags requiring jmps"
0 to: (objectMemory numSlotsOf: arrayObj) - 1 do:
[:i|
classObj := objectMemory fetchPointer: i ofObject: arrayObj.
(objectMemory isImmediateClass: classObj)
ifTrue: [ tag1
ifNil: [tag1 := objectMemory classTagForClass: classObj ]
ifNotNil: [tag2 := objectMemory classTagForClass: classObj ] ] ].
(tag1 = objectMemory smallIntegerTag or: [tag2 = objectMemory smallIntegerTag]) ifTrue:
[(self genJumpSmallIntegerInScratchReg: TempReg) jmpTarget: targetFixUp].
(tag1 = objectMemory characterTag or: [tag2 = objectMemory characterTag]) ifTrue:
[(self genJumpCharacterInScratchReg: TempReg) jmpTarget: targetFixUp].
(tag1 = objectMemory smallFloatTag or: [tag2 = objectMemory smallFloatTag]) ifTrue:
[(self genJumpSmallFloatInScratchReg: TempReg) jmpTarget: targetFixUp].
^ 0
]
{ #category : #'sista support' }
CogObjectRepresentationFor64BitSpur >> branch2CasesIf: reg notInstanceOfBehaviors: arrayObj target: targetFixUp [
"Only 2 immediate type allowed out of the three. Look for the third and jump to target fixup if it's the third.
TempReg currently holds the rcvr tag and the receiver is immediate."
| incorrectTag classObj tag1 tag2 |
< inline: true>
"look for the 2 allowed tags"
0 to: (objectMemory numSlotsOf: arrayObj) - 1 do:
[:i|
classObj := objectMemory fetchPointer: i ofObject: arrayObj.
(objectMemory isImmediateClass: classObj)
ifTrue: [ tag1
ifNil: [tag1 := objectMemory classTagForClass: classObj ]
ifNotNil: [tag2 := objectMemory classTagForClass: classObj ] ] ].
incorrectTag := self fetchImmediateTagOtherThanTag1: tag1 tag2: tag2.
cogit CmpCq: incorrectTag R: TempReg.
cogit JumpZero: targetFixUp.
]
{ #category : #'sista support' }
CogObjectRepresentationFor64BitSpur >> 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:
[jmpImmediate := self genJumpCharacter: reg].
classIndex = objectMemory smallFloatTag ifTrue:
[jmpImmediate := self genJumpSmallFloat: reg].
jmpImmediate jmpTarget: targetFixUp
]
{ #category : #'sista support' }
CogObjectRepresentationFor64BitSpur >> 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:
[jmpImmediate := self genJumpNotCharacter: reg].
classIndex = objectMemory smallFloatTag ifTrue:
[jmpImmediate := self genJumpNotSmallFloat: reg].
jmpImmediate jmpTarget: targetFixUp
]
{ #category : #'in-line cacheing' }
CogObjectRepresentationFor64BitSpur >> classForInlineCacheTag: classIndex [
^objectMemory classOrNilAtIndex: classIndex
]
{ #category : #'sista support' }
CogObjectRepresentationFor64BitSpur >> fetchImmediateTagOtherThanTag1: tag1 tag2: tag2 [
"Answers the immediate tag which is not tag1 nor tag2, usually Character."
<inline: true>
(tag1 = objectMemory characterTag or: [ tag2 = objectMemory characterTag ]) ifFalse:
[ ^ objectMemory characterTag ].
(tag1 = objectMemory smallIntegerTag or: [ tag2 = objectMemory smallIntegerTag ]) ifFalse:
[ ^ objectMemory smallIntegerTag ].
^ objectMemory smallFloatTag
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genAddSmallIntegerTagsTo: aRegister [
cogit AddCq: 1 R: aRegister.
^0
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor64BitSpur >> genAlloc64BitPositiveIntegerValue: valueReg into: resultReg scratchReg: scratch1 scratchReg: scratch2 [
<returnTypeC: #'AbstractInstruction *'>
| allocSize newLPIHeader jumpFail |
allocSize := objectMemory baseHeaderSize + objectMemory wordSize.
newLPIHeader := objectMemory
headerForSlots: 1
format: objectMemory firstByteFormat
classIndex: ClassLargePositiveIntegerCompactIndex.
cogit MoveAw: objectMemory freeStartAddress R: resultReg.
cogit LoadEffectiveAddressMw: allocSize r: resultReg R: scratch1.
cogit CmpCq: objectMemory getScavengeThreshold R: scratch1.
jumpFail := cogit JumpAboveOrEqual: 0.
cogit MoveR: scratch1 Aw: objectMemory freeStartAddress.
self genStoreHeader: newLPIHeader intoNewInstance: resultReg using: scratch1.
cogit MoveR: valueReg Mw: objectMemory baseHeaderSize r: resultReg.
^jumpFail
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor64BitSpur >> genAlloc64BitSignedIntegerValue: valueReg into: resultReg scratchReg: scratch1 scratchReg: scratch2 [
<returnTypeC: #'AbstractInstruction *'>
| allocSize newLNIHeader jumpFail jumpNeg |
allocSize := objectMemory baseHeaderSize + objectMemory wordSize.
newLNIHeader := objectMemory
headerForSlots: 1
format: objectMemory firstByteFormat
classIndex: ClassLargeNegativeIntegerCompactIndex.
cogit MoveAw: objectMemory freeStartAddress R: resultReg.
cogit LoadEffectiveAddressMw: allocSize r: resultReg R: scratch1.
cogit CmpCq: objectMemory getScavengeThreshold R: scratch1.
jumpFail := cogit JumpAboveOrEqual: 0.
cogit MoveR: scratch1 Aw: objectMemory freeStartAddress.
cogit MoveCq: newLNIHeader R: scratch1.
cogit CmpCq: 0 R: valueReg.
jumpNeg := cogit JumpLess: 0.
"We can avoid duplicating the large constant and a jump choosing between
the alternatives by incrementing the single constant if positive. The assert
checks that the hack works. Compact code is to be preferred because it is
an uncommon case; usually the value will fit in a SmallInteger."
self assert: (objectMemory headerForSlots: 0 format: 0 classIndex: 1) = 1.
cogit AddCq: ClassLargePositiveIntegerCompactIndex - ClassLargeNegativeIntegerCompactIndex R: scratch1.
jumpNeg jmpTarget:
(cogit MoveR: scratch1 Mw: 0 r: resultReg).
"The old less compact code was
cogit CmpCq: 0 R: valueReg.
jumpNeg := cogit JumpLess: 0.
cogit MoveCq: newLPIHeader R: scratch1.
jumpJoin := cogit Jump: 0.
jumpNeg jmpTarget:
(cogit MoveCq: newLNIHeader R: scratch1).
jumpJoin jmpTarget:
(cogit MoveR: scratch1 Mw: 0 r: resultReg)."
cogit MoveR: valueReg Mw: objectMemory baseHeaderSize r: resultReg.
^jumpFail
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor64BitSpur >> genAllocFloatValue: dpreg into: resultReg scratchReg: scratch1 scratchReg: scratch2 [
"Override to answer a SmallFloat64 if possible."
<returnTypeC: #'AbstractInstruction *'>
| jumpFail jumpNotSF jumpMerge |
<var: #jumpFail type: #'AbstractInstruction *'>
<var: #jumpNotSF type: #'AbstractInstruction *'>
<var: #jumpMerge type: #'AbstractInstruction *'>
cogit MoveRd: dpreg R: resultReg.
jumpNotSF := self genJumpNotSmallFloatValueBits: resultReg scratch: scratch1.
self genConvertBitsToSmallFloatIn: resultReg scratch: scratch1.
jumpMerge := cogit Jump: 0.
jumpNotSF jmpTarget: cogit Label.
jumpFail := super genAllocFloatValue: dpreg into: resultReg scratchReg: scratch1 scratchReg: scratch2.
jumpMerge jmpTarget: cogit Label.
^jumpFail
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genClearAndSetSmallIntegerTagsIn: scratchReg [
"Set the SmallInteger tag bits when the tag bits may be filled with garbage."
cogit
AndCq: -1 - objectMemory tagMask R: scratchReg;
OrCq: 1 R: scratchReg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genConvertBitsToSmallFloatIn: reg scratch: scratch [
"Convert the in-SmallFloat64-range floating point value in integer register into a tagged SmallFloat64 oop.
c.f. Spur64BitMemoryManager>>smallFloatObjectOf:"
| jumpZero |
<var: #jumpZero type: #'AbstractInstruction *'>
cogit
RotateLeftCq: 1 R: reg;
CmpCq: 1 R: reg.
jumpZero :=
cogit JumpBelowOrEqual: 0.
cogit
SubCq: objectMemory smallFloatExponentOffset << (objectMemory smallFloatMantissaBits + 1) R: reg.
jumpZero jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory numTagBits R: reg).
cogit AddCq: objectMemory smallFloatTag R: reg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genConvertCharacterToSmallIntegerInReg: reg [
"Convert the Character in reg to a SmallInteger, assuming
the Character's value is a valid character."
cogit SubCq: objectMemory characterTag - objectMemory smallIntegerTag R: reg
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genConvertIntegerToSmallIntegerInReg: reg [
cogit LogicalShiftLeftCq: objectMemory numTagBits R: reg.
cogit AddCq: 1 R: reg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genConvertSmallFloatToSmallFloatHashAsIntegerInReg: reg scratch: scratch [
"Convert the SmallFloat in reg to its identityHash as a SmallInteger.
Rotate the sign bit from bit 3 (zero-relative) to the sign bit.
c.f. Spur64BitMemoryManager>>rotatedFloatBitsOf:"
self assert: objectMemory smallFloatTag >> 1 - objectMemory smallIntegerTag = objectMemory smallIntegerTag.
cogit
LogicalShiftRightCq: 1 R: reg;
AndCq: 1 << (objectMemory numTagBits - 1) R: reg R: scratch;
SubR: scratch R: reg;
SubCq: objectMemory smallFloatTag >> 1 - objectMemory smallIntegerTag R: reg;
LogicalShiftLeftCq: 63 - (objectMemory numTagBits - 1) R: scratch;
OrR: scratch R: reg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genConvertSmallIntegerToCharacterInReg: reg [
"Convert the SmallInteger in reg to a Character, assuming
the SmallInteger's value is a valid character."
cogit AddCq: objectMemory characterTag - objectMemory smallIntegerTag R: reg
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genConvertSmallIntegerToIntegerInReg: reg [
cogit ArithmeticShiftRightCq: objectMemory numTagBits R: reg.
^0
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor64BitSpur >> genDoubleArithmetic: arithmeticOperator preOpCheck: preOpCheckOrNil [
<inline: true>
^self genFloatArithmetic: arithmeticOperator preOpCheck: preOpCheckOrNil boxed: true
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor64BitSpur >> genDoubleComparison: jumpOpcodeGenerator invert: invertComparison [
<inline: true>
^self genFloatComparison: jumpOpcodeGenerator invert: invertComparison boxed: true
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genFetchIndexRegister: indexReg from: tableObj into: destReg [
"indexReg contains the 1-relative index of an element in tableObj.
Since BaseHeaderSize = BytesPerOop we can use it as a
zero-relative index from the beginning of the object."
self assert: indexReg ~= destReg.
cogit genMoveConstant: tableObj R: destReg.
cogit MoveXwr: indexReg R: destReg R: destReg.
^0
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor64BitSpur >> genFloatArithmetic: arithmeticOperator preOpCheck: preOpCheckOrNil boxed: rcvrBoxed [
<var: #preOpCheckOrNil declareC: 'AbstractInstruction *(*preOpCheckOrNil)(int rcvrReg, int argReg)'>
<inline: false>
| jumpFailAlloc jumpFailCheck jumpImmediate jumpNotSmallFloat jumpNotSmallInteger jumpNotBoxedFloat doOp |
<var: #jumpNotSmallInteger type: #'AbstractInstruction *'>
<var: #jumpNotBoxedFloat type: #'AbstractInstruction *'>
<var: #jumpNotSmallFloat type: #'AbstractInstruction *'>
<var: #jumpImmediate type: #'AbstractInstruction *'>
<var: #jumpFailCheck type: #'AbstractInstruction *'>
<var: #jumpFailAlloc type: #'AbstractInstruction *'>
<var: #doOp type: #'AbstractInstruction *'>
cogit genLoadArgAtDepth: 0 into: Arg0Reg.
rcvrBoxed
ifTrue: [self genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0]
ifFalse: [self genGetSmallFloatValueOf: ReceiverResultReg scratch: TempReg into: DPFPReg0].
jumpNotSmallFloat := self genJumpNotSmallFloat: Arg0Reg.
self genGetSmallFloatValueOf: Arg0Reg scratch: TempReg into: DPFPReg1.
doOp := cogit Label.
preOpCheckOrNil ifNotNil:
[jumpFailCheck := cogit perform: preOpCheckOrNil with: DPFPReg0 with: DPFPReg1].
cogit gen: arithmeticOperator operand: DPFPReg1 operand: DPFPReg0.
jumpFailAlloc := self genAllocFloatValue: DPFPReg0 into: SendNumArgsReg scratchReg: ClassReg scratchReg: TempReg.
cogit MoveR: SendNumArgsReg R: ReceiverResultReg.
cogit genPrimReturn.
jumpNotSmallFloat jmpTarget: cogit Label.
jumpNotSmallInteger := self genJumpNotSmallInteger: Arg0Reg.
cogit MoveR: Arg0Reg R: Arg1Reg.
self genConvertSmallIntegerToIntegerInReg: Arg1Reg.
cogit ConvertR: Arg1Reg Rd: DPFPReg1.
cogit Jump: doOp.
jumpNotSmallInteger jmpTarget: cogit Label.
jumpImmediate := self genJumpImmediate: Arg0Reg.
self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg.
self genCmpClassFloatCompactIndexR: SendNumArgsReg.
jumpNotBoxedFloat := cogit JumpNonZero: 0.
self genGetDoubleValueOf: Arg0Reg into: DPFPReg1.
cogit Jump: doOp.
jumpImmediate jmpTarget:
(jumpNotBoxedFloat jmpTarget:
(jumpNotSmallInteger jmpTarget:
(jumpFailAlloc jmpTarget: cogit Label))).
preOpCheckOrNil ifNotNil:
[jumpFailCheck jmpTarget: jumpFailAlloc getJmpTarget].
^0
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor64BitSpur >> genFloatComparison: jumpOpcodeGenerator invert: invertComparison boxed: rcvrBoxed [
<var: #jumpOpcodeGenerator declareC: 'AbstractInstruction *(*jumpOpcodeGenerator)(void *)'>
<inline: false>
| jumpImmediate jumpNotSmallFloat jumpNotSmallInteger jumpNotBoxedFloat jumpCond compare |
<var: #jumpNotSmallInteger type: #'AbstractInstruction *'>
<var: #jumpNotBoxedFloat type: #'AbstractInstruction *'>
<var: #jumpNotSmallFloat type: #'AbstractInstruction *'>
<var: #jumpImmediate type: #'AbstractInstruction *'>
<var: #jumpCond type: #'AbstractInstruction *'>
cogit genLoadArgAtDepth: 0 into: Arg0Reg.
rcvrBoxed
ifTrue: [self genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0]
ifFalse: [self genGetSmallFloatValueOf: ReceiverResultReg scratch: TempReg into: DPFPReg0].
jumpNotSmallFloat := self genJumpNotSmallFloat: Arg0Reg.
self genGetSmallFloatValueOf: Arg0Reg scratch: TempReg into: DPFPReg1.
compare := invertComparison "May need to invert for NaNs"
ifTrue: [cogit CmpRd: DPFPReg0 Rd: DPFPReg1]
ifFalse: [cogit CmpRd: DPFPReg1 Rd: DPFPReg0].
jumpCond := cogit perform: jumpOpcodeGenerator with: 0. "FP jumps are a little weird"
cogit genMoveFalseR: ReceiverResultReg.
cogit genPrimReturn.
jumpCond jmpTarget: (cogit genMoveTrueR: ReceiverResultReg).
cogit genPrimReturn.
jumpNotSmallFloat jmpTarget: cogit Label.
jumpNotSmallInteger := self genJumpNotSmallInteger: Arg0Reg.
self genConvertSmallIntegerToIntegerInReg: Arg0Reg.
cogit ConvertR: Arg0Reg Rd: DPFPReg1.
cogit Jump: compare.
jumpNotSmallInteger jmpTarget: cogit Label.
jumpImmediate := self genJumpImmediate: Arg0Reg.
self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg.
self genCmpClassFloatCompactIndexR: SendNumArgsReg.
jumpNotBoxedFloat := cogit JumpNonZero: 0.
self genGetDoubleValueOf: Arg0Reg into: DPFPReg1.
cogit Jump: compare.
jumpImmediate jmpTarget:
(jumpNotBoxedFloat jmpTarget: cogit Label).
^CompletePrimitive
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genGetHashFieldNonImmOf: instReg asSmallIntegerInto: destReg [
"Fetch the instance's identity hash into destReg, encoded as a SmallInteger."
cogit
MoveMw: 0 r: instReg R: destReg;
"Shift and mask the field leaving room for the SmallInteger tag."
LogicalShiftRightCq: objectMemory identityHashFullWordShift - objectMemory numTagBits R: destReg;
AndCq: objectMemory identityHashHalfWordMask << objectMemory numTagBits R: destReg;
AddCq: objectMemory smallIntegerTag R: destReg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genGetHashFieldNonImmOf: instReg into: destReg [
"Fetch the instance's identity hash into destReg, unencoded."
cogit
MoveMw: 0 r: instReg R: destReg;
LogicalShiftRightCq: 32 R: destReg;
AndCq: objectMemory identityHashHalfWordMask R: destReg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> 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, or
the receiver's classIndex. Answer the label for the start of the sequence."
| jumpImm entryLabel |
<var: #jumpImm type: #'AbstractInstruction *'>
<var: #entryLabel type: #'AbstractInstruction *'>
forEntry ifTrue:
[cogit AlignmentNops: objectMemory wordSize].
entryLabel := cogit Label.
cogit AndCq: objectMemory tagMask R: sourceReg R: destReg.
jumpImm := cogit JumpNonZero: 0.
"Get least significant half of header word in destReg"
self flag: #endianness.
cogit MoveMw: 0 r: sourceReg R: destReg.
cogit AndCq: objectMemory classIndexMask R: destReg.
jumpImm jmpTarget: cogit Label.
^entryLabel
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> 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: 7).
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: 7 ofFormatByteOf: srcReg into: TempReg.
"Now: fmt bitAnd: 3 in TempReg"
cogit SubR: TempReg R: destReg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genGetOverflowSlotsOf: srcReg into: destReg [
cogit
MoveMw: objectMemory baseHeaderSize negated r: srcReg R: destReg;
LogicalShiftLeftCq: 8 R: destReg;
LogicalShiftRightCq: 8 R: destReg.
^0
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor64BitSpur >> 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 jumpIs32BitLongs jumpIsContext |
<inline: true>
"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.
jumpIs32BitLongs := cogit JumpGreaterOrEqual: 0.
cogit CmpCq: objectMemory sixtyFourBitIndexableFormat R: formatReg.
jump64BitLongsDone := cogit JumpZero: 0.
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: objectMemory wordSize >> 1 - 1 R: formatReg.
cogit SubR: formatReg R: destReg.
jumpShortsDone := cogit Jump: 0.
jumpIs32BitLongs jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord - 2 R: destReg).
cogit AndCq: objectMemory wordSize >> 2 - 1 R: formatReg.
cogit SubR: formatReg R: destReg.
jump32BitLongsDone := 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.
self genGetClassObjectOfClassIndex: formatReg into: Extra0Reg scratchReg: scratchReg.
self genLoadSlot: InstanceSpecificationIndex sourceReg: Extra0Reg destReg: formatReg.
self genConvertSmallIntegerToIntegerInReg: formatReg.
cogit
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' }
CogObjectRepresentationFor64BitSpur >> genGetSmallFloatValueOf: oopReg scratch: scratch into: dpReg [
"Convert the SmallFloat oop in ooppReg into the corresponding float value in dpReg.
c.f. Spur64BitMemoryManager>>smallFloatBitsOf:"
| jumpSFZero |
<var: 'jumpSFZero' type: #'AbstractInstruction *'>
cogit
MoveR: oopReg R: scratch;
LogicalShiftRightCq: objectMemory numTagBits R: scratch;
CmpCq: 1 R: scratch.
jumpSFZero := cogit JumpLessOrEqual: 0.
cogit AddCq: objectMemory smallFloatExponentOffset << (objectMemory smallFloatMantissaBits + 1) R: scratch.
jumpSFZero jmpTarget: (cogit RotateRightCq: 1 R: scratch).
cogit MoveR: scratch Rd: dpReg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpCharacter: reg [
"Generate a compare and branch to test if aRegister contains a Character."
^cogit
TstCq: objectMemory characterTag R: reg;
JumpNonZero: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpCharacterInScratchReg: aRegister [
^self genJumpCharacter: aRegister
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> 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. Spur64BitMemoryManager>>isIntegerValue:"
<returnTypeC: #'AbstractInstruction *'>
^cogit
MoveR: aRegister R: scratchReg;
ArithmeticShiftRightCq: 63 - objectMemory numTagBits R: scratchReg;
AddCq: 1 R: scratchReg;
AndCq: 1 << (objectMemory numTagBits + 1) - 1 R: scratchReg; "sign and top numTags bits must be the same"
CmpCq: 1 R: scratchReg;
JumpLessOrEqual: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpNotCharacter: reg [
"Generate a compare and branch to test if aRegister contains other than a Character."
^cogit
TstCq: objectMemory characterTag R: reg;
JumpZero: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpNotCharacterInScratchReg: reg [
<inline: true>
^self genJumpNotCharacter: reg
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpNotSmallFloat: reg [
"Generate a compare and branch to test if aRegister contains other than a SmallFloat.
Answer the jump."
^cogit
TstCq: objectMemory smallFloatTag R: reg;
JumpZero: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpNotSmallFloatInScratchReg: aRegister [
<inline: true>
^self genJumpNotSmallFloat: aRegister
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpNotSmallFloatValueBits: reg scratch: exponent [
"Generate a test to check that the integer register contains a floating point value within the SmallFloat64 range,
and answer the jump. c.f. Spur64BitMemoryManager>>isSmallFloatValue:"
| jumpFail jumpTest jumpMinExponent jumpMaxExponent jumpZeroMantissa |
<var: #jumpFail type: #'AbstractInstruction *'>
<var: #jumpTest type: #'AbstractInstruction *'>
<var: #jumpMinExponent type: #'AbstractInstruction *'>
<var: #jumpMaxExponent type: #'AbstractInstruction *'>
<var: #jumpZeroMantissa type: #'AbstractInstruction *'>
self flag: 'if we combine the exponent range test with the conversion to tagged representation we test for a zero exponent only once. further, if we extract tags once into a scratch on the input side we test for immediates, SmallInteger and SmallFloat using the same intermediate result. so to do is to move fp arithmetic into the object representations'.
cogit MoveR: reg R: exponent.
true
ifTrue: [cogit
LogicalShiftLeftCq: 1 R: exponent; "drop sign"
LogicalShiftRightCq: objectMemory smallFloatMantissaBits + 1 R: exponent] "shift exponent down"
ifFalse: [cogit
LogicalShiftRightCq: objectMemory smallFloatMantissaBits R: exponent;
AndCq: 16r7FF R: exponent]. "ieee double precision mantissa is 11 bits"
cogit CmpCq: objectMemory smallFloatExponentOffset R: exponent.
jumpMinExponent := cogit JumpLessOrEqual: 0.
cogit CmpCq: 255 + objectMemory smallFloatExponentOffset R: exponent. "SmallFloat exponent is 8 bits"
jumpMaxExponent := cogit JumpLessOrEqual: 0.
jumpFail :=
cogit Jump: 0.
jumpMinExponent jmpTarget:
(cogit TstCq: 1 << objectMemory smallFloatMantissaBits - 1 R: reg). "test mantissa bits"
jumpZeroMantissa := cogit JumpZero: 0.
cogit CmpCq: objectMemory smallFloatExponentOffset R: exponent.
jumpTest :=
cogit Jump: 0.
jumpZeroMantissa jmpTarget:
(cogit CmpCq: 0 R: exponent).
jumpTest jmpTarget:
(cogit JumpNonZero: jumpFail).
jumpMaxExponent jmpTarget: cogit Label.
^jumpFail
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpNotSmallInteger: reg [
"Generate a compare and branch to test if aRegister contains other than a SmallInteger."
^cogit
TstCq: objectMemory smallIntegerTag R: reg;
JumpZero: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpNotSmallIntegerInScratchReg: aRegister [
<inline: true>
^self genJumpNotSmallInteger: aRegister
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> 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. Spur64BitMemoryManager>>isIntegerValue:"
<returnTypeC: #'AbstractInstruction *'>
^cogit
MoveR: aRegister R: scratchReg;
ArithmeticShiftRightCq: 64 - objectMemory numTagBits R: scratchReg;
AddCq: 1 R: scratchReg;
AndCq: 1 << (objectMemory numTagBits + 1) - 1 R: scratchReg; "sign and top numTags bits must be the same"
CmpCq: 1 R: scratchReg;
JumpGreater: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpSmallFloat: aRegister [
"Generate a compare and branch to test if aRegister contains a SmallFloat.
Answer the jump, or UnimplementedOperation if this cannot be done with
a single register."
^cogit
TstCq: objectMemory smallFloatTag R: aRegister;
JumpNonZero: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpSmallFloatInScratchReg: aRegister [
^self genJumpSmallFloat: aRegister
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpSmallInteger: aRegister [
"Generate a compare and branch to test if aRegister contains a SmallInteger.
Answer the jump, or UnimplementedOperation if this cannot be done with
a single register."
^cogit
TstCq: objectMemory smallIntegerTag R: aRegister;
JumpNonZero: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor64BitSpur >> genJumpSmallIntegerInScratchReg: aRegister [
^self genJumpSmallInteger: aRegister
]
{ #category : #'inline primitive support' }
CogObjectRepresentationFor64BitSpur >> genLcInt32ToOop: value [
<option: #LowcodeVM>
cogit SignExtend32R: value R: value.
self genConvertIntegerToSmallIntegerInReg: value.
cogit ssPushRegister: value.
^ 0
]
{ #category : #'inline primitive support' }
CogObjectRepresentationFor64BitSpur >> genLcOopToInt32: value [
<option: #LowcodeVM>
self genConvertSmallIntegerToIntegerInReg: value.
cogit ssPushNativeRegister: value.
^ 0
]
{ #category : #'inline primitive support' }
CogObjectRepresentationFor64BitSpur >> genLcOopToUInt32: value [
<option: #LowcodeVM>
self genConvertSmallIntegerToIntegerInReg: value.
cogit ssPushNativeRegister: value.
^ 0
]
{ #category : #'inline primitive support' }
CogObjectRepresentationFor64BitSpur >> genLcUInt32ToOop: value [
<option: #LowcodeVM>
cogit ZeroExtend32R: value R: value.
self genConvertIntegerToSmallIntegerInReg: value.
cogit ssPushRegister: value.
^ 0
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor64BitSpur >> 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 jumpIsWords jumpHasFixedFields
jumpArrayOutOfBounds jumpFixedFieldsOutOfBounds
jumpWordsOutOfBounds jumpShortsOutOfBounds jumpBytesOutOfBounds
jumpShortsOutOfRange jumpWordsOutOfRange jumpBytesOutOfRange jumpDoubleWordsOutOfRange
jumpNonSmallIntegerValue jumpNotPointers
rejoin jumpNegative jump64BitsOutOfBounds jumpNot64BitIndexable jump64BitArgIsImmediate jumpNot8ByteInteger
|
"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"
self genGetClassObjectOfClassIndex: formatReg into: Extra0Reg scratchReg: TempReg.
self genLoadSlot: InstanceSpecificationIndex sourceReg: Extra0Reg destReg: formatReg.
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.
jumpIsWords := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory sixtyFourBitIndexableFormat R: formatReg.
jumpNotIndexableBits := cogit JumpNonZero: 0.
"fall through to 64-bit words"
cogit MoveR: Arg1Reg R: SendNumArgsReg.
self genConvertSmallIntegerToIntegerInReg: SendNumArgsReg.
signedVersion ifFalse:
[cogit CmpCq: 0 R: SendNumArgsReg.
jumpNegative := cogit JumpLess: 0].
rejoin :=
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jump64BitsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg0Reg.
cogit MoveR: SendNumArgsReg Xwr: Arg0Reg R: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
"Handle LargePositiveInteger (unsigned) or LargePositiveInteger and LargeNegativeInteger (signed)
for sixtyFourBitIndexableFormat"
jumpNonSmallIntegerValue jmpTarget:
(cogit CmpCq: objectMemory sixtyFourBitIndexableFormat R: formatReg).
jumpNot64BitIndexable := cogit JumpNonZero: 0.
jump64BitArgIsImmediate := self genJumpImmediate: Arg1Reg.
signedVersion ifTrue: "Test top bit of 64-bit word in large integer for range check."
[cogit MoveMw: objectMemory baseHeaderSize r: Arg1Reg R: TempReg.
cogit CmpCq: 0 R: TempReg.
jumpDoubleWordsOutOfRange := cogit JumpLess: 0].
"Now check if the header is that of an 8 byte LargePositiveInteger"
cogit MoveMw: 0 r: Arg1Reg R: SendNumArgsReg.
cogit AndCq: (objectMemory
headerForSlots: objectMemory numSlotsMask
format: objectMemory formatMask
classIndex: objectMemory classIndexMask)
R: SendNumArgsReg.
cogit CmpCq: (objectMemory
headerForSlots: 1
format: objectMemory firstByteFormat
classIndex: ClassLargePositiveIntegerCompactIndex)
R: SendNumArgsReg.
jumpNot8ByteInteger := cogit JumpNonZero: 0.
cogit MoveMw: objectMemory baseHeaderSize r: Arg1Reg R: SendNumArgsReg.
cogit Jump: rejoin.
signedVersion ifTrue:
["Now check if the header is that of an 8 byte LargeNegativeInteger"
jumpNot8ByteInteger jmpTarget:
(cogit CmpCq: (objectMemory
headerForSlots: 1
format: objectMemory firstByteFormat
classIndex: ClassLargeNegativeIntegerCompactIndex)
R: SendNumArgsReg).
jumpNot8ByteInteger := cogit JumpNonZero: 0.
cogit MoveMw: objectMemory baseHeaderSize r: Arg1Reg R: TempReg.
cogit MoveCq: 0 R: SendNumArgsReg.
cogit SubR: TempReg R: SendNumArgsReg.
cogit Jump: rejoin].
signedVersion
ifTrue:
[jumpIsWords jmpTarget:
(cogit MoveR: SendNumArgsReg R: TempReg).
cogit ArithmeticShiftRightCq: 31 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:
[jumpIsWords jmpTarget:
(cogit CmpCq: (objectMemory integerObjectOf: 16rFFFFFFFF) R: Arg1Reg)].
jumpWordsOutOfRange := cogit JumpAbove: 0.
cogit LogicalShiftLeftCq: objectMemory shiftForWord - 2 R: nSlotsOrBytesReg.
cogit AndCq: objectMemory wordSize / 4 - 1 R: formatReg.
cogit SubR: formatReg R: nSlotsOrBytesReg.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpWordsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit MoveR: Arg1Reg R: TempReg.
self genConvertSmallIntegerToIntegerInReg: TempReg.
cogit AddCq: objectMemory baseHeaderSize >> (objectMemory shiftForWord - 1) R: Arg0Reg.
cogit MoveR: TempReg X32r: 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.