-
Notifications
You must be signed in to change notification settings - Fork 69
/
CogSimStackEntry.class.st
361 lines (304 loc) · 9.96 KB
/
CogSimStackEntry.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
"
A CogSimStackEntry represents an object pushed on the stack, but during the partial evaluation that occurs as part of the StackToRegisterMappingCogit's compilation. Bytecodes that produce operands (push items onto the stack) push suitably descriptive instances of CogSimStackEntry onto the simStack (simulation stack). Bytecodes that consume operands (sends, assignments, returns, etc) take items off the simStack. Hence the generated code avoids pushing items onto the real stack, and the StackToRegisterMappngCogit can put the operands found on the simStack in registers, etc. Hence actual stack traffic is much reduced, a much more efficient calling convention is enabled, and so overall performance is increased. This scheme is due to L. Peter Deutsch and extended here.
Instance Variables
bcptr: <Integer>
cogit: <StackToRegisterMappingCogit>
constant: <Oop>
liveRegister: <Integer>
objectRepresentation: <CogObjectRepresentation>
offset: <Integer>
register: <Integer>
spilled: <Boolean>
type: <Integer from SSBaseOffset, SSConstant, SSRegister or SSSpill>
bcptr
- the bytecode PC at which this particular entry was created (pushed onto the stack).
cogit
- the StackToRegisterMappingCogit using this instance
constant
- if type = SSConstant then this is the constant's oop
liveRegister
- unused other than for simSelf. This is here for simSelf and for the subclass CogRegisterAllocatingSimStackEntry
objectRepresentation
- the CogObjectRepresentation in use for the current object model
offset
- if type = SSBaseOffset or type = SSSpill then this is the offset from register
register
- type = SSBaseOffset or type = SSSpill or type = SSRegister then this is the register's code (NoReg, TempReg, ReceiverResultReg et al)
spilled
- if true, then this entry has been spilled onto the actual stack (or rather code has been generated to push the entry onto the real stack)
type
- SSBaseOffset, SSConstant, SSRegister or SSSpill
"
Class {
#name : #CogSimStackEntry,
#superclass : #VMStructType,
#instVars : [
'cogit',
'objectRepresentation',
'type',
'spilled',
'liveRegister',
'registerr',
'offset',
'constant',
'bcptr'
],
#pools : [
'CogAbstractRegisters',
'CogCompilationConstants',
'CogRTLOpcodes',
'VMStackFrameOffsets'
],
#category : #'VMMaker-JIT'
}
{ #category : #'simulation only' }
CogSimStackEntry class >> byteSizeForSimulator: aVMClass [
"Answer an approximation of the byte size of an AbstractInstruction struct.
This is for estimating the alloca in allocateOpcodes:bytecodes:ifFail:"
^self instSize * (aVMClass sizeof: #'void *')
]
{ #category : #translation }
CogSimStackEntry class >> instVarNamesAndTypesForTranslationDo: aBinaryBlock [
"Enumerate aBinaryBlock with the names and C type strings for the inst vars to include in a CogSimStackEntry struct."
"self typedef"
self filteredInstVarNames do:
[:ivn|
aBinaryBlock
value: ivn
value: (ivn caseOf: {
['type'] -> [#char].
['spilled'] -> [#char].
['registerr'] -> [#'signed char']. "because NoReg = -1"
['liveRegister'] -> [#'signed char'].}
otherwise:
[#sqInt])]
]
{ #category : #translation }
CogSimStackEntry class >> structTypeName [
^'SimStackEntry'
]
{ #category : #accessing }
CogSimStackEntry >> base [
self assert: (self type == SSSpill or: [self type == SSBaseOffset]).
^ registerr
]
{ #category : #accessing }
CogSimStackEntry >> bcptr [
"Answer the value of bcptr"
^ bcptr
]
{ #category : #accessing }
CogSimStackEntry >> bcptr: anObject [
"Set the value of bcptr"
^bcptr := anObject
]
{ #category : #accessing }
CogSimStackEntry >> cogit [
"Answer the value of cogit"
<doNotGenerate>
^cogit
]
{ #category : #'initialize-release' }
CogSimStackEntry >> cogit: aCogit [
<doNotGenerate>
cogit := aCogit.
objectRepresentation := cogit objectRepresentation.
^self
]
{ #category : #accessing }
CogSimStackEntry >> constant [
"Answer the value of constant"
self assert: type = SSConstant.
^constant
]
{ #category : #accessing }
CogSimStackEntry >> constant: anObject [
"Set the value of constant"
^constant := anObject
]
{ #category : #'compile abstract instructions' }
CogSimStackEntry >> copyToReg: reg [
"Copy the value of the current entry to the register argument.
Do not touch the stack"
type caseOf: {
[SSBaseOffset] -> [cogit MoveMw: offset r: registerr R: reg].
[SSSpill] -> [cogit MoveMw: offset r: registerr R: reg].
[SSConstant] -> [cogit genMoveConstant: constant R: reg].
[SSRegister] -> [reg = registerr
ifTrue: [cogit Label]
ifFalse: [cogit MoveR: registerr R: reg]] }
]
{ #category : #'compile abstract instructions' }
CogSimStackEntry >> ensureSpilledAt: baseOffset from: baseRegister [
| inst |
<var: #inst type: #'AbstractInstruction *'>
spilled ifTrue:
[type = SSSpill ifTrue:
[self assert: ((offset = baseOffset and: [registerr = baseRegister]) or: [cogit violatesEnsureSpilledSpillAssert]).
^self]].
self assert: type ~= SSSpill.
cogit traceSpill: self.
type = SSConstant
ifTrue:
[inst := cogit genPushConstant: constant]
ifFalse:
[type = SSBaseOffset
ifTrue:
[cogit MoveMw: offset r: registerr R: TempReg.
inst := cogit PushR: TempReg]
ifFalse:
[self assert: type = SSRegister.
inst := cogit PushR: registerr].
type := SSSpill.
offset := baseOffset.
registerr := baseRegister].
spilled := true.
]
{ #category : #accessing }
CogSimStackEntry >> floatRegisterMask [
^ 0
]
{ #category : #comparing }
CogSimStackEntry >> isFrameSimSelf [
"Answer if the receiver is self. This only works in a frameful method, hence the weird name."
<inline: true>
^type = SSBaseOffset and: [registerr = FPReg and: [offset = FoxMFReceiver]]
]
{ #category : #comparing }
CogSimStackEntry >> isFrameTempVar [
"Answer if the receiver is a temporary variable. This
only works in a frameful method, hence the weird name."
<inline: true>
^type = SSBaseOffset and: [registerr = FPReg and: [offset ~= FoxMFReceiver]]
]
{ #category : #comparing }
CogSimStackEntry >> isFrameVar [
"Answer if the receiver is a temporary variable or self. This
only works in a frameful method, hence the weird name."
<inline: true>
^type = SSBaseOffset and: [registerr = FPReg]
]
{ #category : #comparing }
CogSimStackEntry >> isSameEntryAs: ssEntry [
<var: 'ssEntry' type: #'CogSimStackEntry *'>
^type = ssEntry type
and: [((type = SSBaseOffset or: [type == SSSpill]) and: [offset = ssEntry offset and: [registerr = ssEntry registerr]])
or: [(type = SSRegister and: [registerr = ssEntry registerr])
or: [(type = SSConstant and: [constant = ssEntry constant])]]]
]
{ #category : #accessing }
CogSimStackEntry >> liveRegister [
^ liveRegister
]
{ #category : #accessing }
CogSimStackEntry >> liveRegister: anObject [
^liveRegister := anObject
]
{ #category : #accessing }
CogSimStackEntry >> maybeConstant [
"Answer the value of constant, no assert check."
<cmacro: '(sse) ((sse)->constant)'>
^constant
]
{ #category : #'compile abstract instructions' }
CogSimStackEntry >> moveToVectorReg: reg [
self assert: type = SSVectorRegister.
spilled
ifTrue:
[self notYetImplemented]
ifFalse:
[type caseOf: {
[SSVectorRegister] -> [reg ~= registerr
ifTrue: [self notYetImplemented]
ifFalse: [cogit Label]] }]
]
{ #category : #accessing }
CogSimStackEntry >> offset [
"Answer the value of offset"
self assert: (self type == SSSpill or: [self type == SSBaseOffset]).
^offset
]
{ #category : #accessing }
CogSimStackEntry >> offset: anObject [
"Set the value of offset"
^offset := anObject
]
{ #category : #printing }
CogSimStackEntry >> printStateOn: aStream [
<doNotGenerate> "Smalltalk-side only"
type isInteger ifFalse: [^self].
aStream nextPut: $(.
type caseOf: {
[SSBaseOffset] -> [aStream
nextPutAll: 'bo ';
nextPutAll: (cogit backEnd nameForRegister: registerr).
offset negative ifFalse: [aStream nextPut: $+].
aStream print: offset].
[SSConstant] -> [aStream
nextPutAll: 'const ';
nextPutAll: (cogit coInterpreter shortPrint: constant)].
[SSRegister] -> [aStream
nextPutAll: 'reg ';
nextPutAll: (cogit backEnd nameForRegister: registerr)].
[SSSpill] -> [aStream
nextPutAll: 'spill @ ';
nextPutAll: (cogit backEnd nameForRegister: registerr).
offset negative ifFalse: [aStream nextPut: $+].
aStream print: offset].
[SSVectorRegister] -> [ aStream
nextPutAll: 'Vector Register ';
print: registerr ] }.
(spilled and: [type ~= SSSpill]) ifTrue:
[aStream nextPutAll: ' (spilled)'].
bcptr ifNotNil:
[aStream space; nextPut: ${; print: bcptr; nextPut: $}].
aStream nextPut: $)
]
{ #category : #accessing }
CogSimStackEntry >> registerMask [
"Answer a bit mask for the receiver's register, if any."
^ (type = SSBaseOffset or: [ type = SSRegister or: [ type = SSVectorRegister ] ])
ifTrue: [ cogit registerMaskFor: registerr ]
ifFalse: [ 0 ]
]
{ #category : #accessing }
CogSimStackEntry >> registerMaskOrNone [
^(type = SSRegister or: [ type = SSVectorRegister ]) ifTrue: [cogit registerMaskFor: registerr] ifFalse: [0]
]
{ #category : #accessing }
CogSimStackEntry >> registerOrNone [
^ ((type = SSRegister) or: [ type = SSVectorRegister ])
ifTrue: [registerr]
ifFalse: [NoReg]
]
{ #category : #accessing }
CogSimStackEntry >> registerr [
"Answer the value of register"
self assert: (type = SSBaseOffset or: [type = SSRegister or: [type = SSVectorRegister]]).
^registerr
]
{ #category : #accessing }
CogSimStackEntry >> registerr: anObject [
"Set the value of register"
^registerr := anObject
]
{ #category : #accessing }
CogSimStackEntry >> spilled [
"Answer the value of spilled"
^ spilled
]
{ #category : #accessing }
CogSimStackEntry >> spilled: anObject [
"Set the value of spilled"
^spilled := anObject
]
{ #category : #accessing }
CogSimStackEntry >> type [
"Answer the value of type"
^ type
]
{ #category : #accessing }
CogSimStackEntry >> type: anObject [
"Set the value of type"
^type := anObject
]