[Vm-dev] VM Maker: VMMaker.oscog-cb.1186.mcz
commits at source.squeak.org
commits at source.squeak.org
Mon Apr 13 20:15:24 UTC 2015
ClementBera uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-cb.1186.mcz
==================== Summary ====================
Name: VMMaker.oscog-cb.1186
Author: cb
Time: 13 April 2015, 1:13:39.752 pm
UUID: 238dfa51-a02c-438a-9bd3-5e48cd33b24f
Ancestors: VMMaker.oscog-cb.1185
Added with Eliot some abstraction other register allocation. This is now used in inline primitives.
=============== Diff against VMMaker.oscog-cb.1185 ===============
Item was changed:
----- Method: CogAbstractInstruction>>availableRegisterOrNilFor: (in category 'register allocation') -----
availableRegisterOrNilFor: liveRegsMask
"Answer an unused abstract register in the liveRegMask.
Subclasses with more registers can override to answer them."
<returnTypeC: #sqInt>
self flag: 'searching physical registers that are not assigned to abstract registers first will do a better job and allocate with fewer conflicts'.
+ (cogit register: Arg1Reg isInMask: liveRegsMask) ifFalse:
- (liveRegsMask anyMask: (cogit registerMaskFor: Arg1Reg)) ifFalse:
[^Arg1Reg].
+ (cogit register: Arg0Reg isInMask: liveRegsMask) ifFalse:
- (liveRegsMask anyMask: (cogit registerMaskFor: Arg0Reg)) ifFalse:
[^Arg0Reg].
+ (cogit register: SendNumArgsReg isInMask: liveRegsMask) ifFalse:
- (liveRegsMask anyMask: (cogit registerMaskFor: SendNumArgsReg)) ifFalse:
[^SendNumArgsReg].
+ (cogit register: ClassReg isInMask: liveRegsMask) ifFalse:
- (liveRegsMask anyMask: (cogit registerMaskFor: ClassReg)) ifFalse:
[^ClassReg].
+ (cogit register: ReceiverResultReg isInMask: liveRegsMask) ifFalse:
- (liveRegsMask anyMask: (cogit registerMaskFor: ReceiverResultReg)) ifFalse:
[^ReceiverResultReg].
^nil!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>allocateOneRegister (in category 'simulation stack') -----
+ allocateOneRegister
+
+ | rTop |
+
+ self ssTop type = SSRegister ifTrue: [ ^ self ssTop register].
+
+ rTop := self allocateRegisterNotConflictingWith: 0.
+
+ rTop = ReceiverResultReg ifTrue:
+ [ optStatus isReceiverResultRegLive: false ].
+
+ ^ rTop
+
+ !
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>allocateRegisterNotConflictingWith: (in category 'simulation stack') -----
+ allocateRegisterNotConflictingWith: registerMask
+ | reg |
+ "if there's a free register, use it"
+ reg := backEnd availableRegisterOrNilFor: (self liveRegisters bitOr: registerMask).
+ reg ifNotNil: [^ reg].
+ "No free register, choose one that does not conflict with registerMask"
+ ^ self freeRegisterNotConflictingWith: registerMask!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>allocateThreeRegistersInto:thirdIsReceiver: (in category 'simulation stack') -----
+ allocateThreeRegistersInto: trinaryBlock thirdIsReceiver: thirdIsReceiver
+ | topRegistersMask rTop rNext rThird needsThirdRegUpdate |
+
+ topRegistersMask := 0.
+ needsThirdRegUpdate := true.
+
+ (self ssTop type = SSRegister and: [ thirdIsReceiver not or: [ self ssTop register ~= ReceiverResultReg ] ]) ifTrue:
+ [ topRegistersMask := self registerMaskFor: (rTop := self ssTop register)].
+ ((self ssValue: 1) type = SSRegister and: [ thirdIsReceiver not or: [ (self ssValue: 1) register ~= ReceiverResultReg ] ]) ifTrue:
+ [ topRegistersMask := topRegistersMask bitOr: (self registerMaskFor: (rNext := (self ssValue: 1) register))].
+ ((self ssValue: 2) type = SSRegister and: [thirdIsReceiver not or: [ (self ssValue: 2) register = ReceiverResultReg ] ]) ifTrue:
+ [ needsThirdRegUpdate := false.
+ topRegistersMask := topRegistersMask bitOr: (self registerMaskFor: (rThird := (self ssValue: 2) register))].
+
+ rThird ifNil:
+ [ thirdIsReceiver
+ ifTrue: "Is ReceiverResultReg free ?"
+ [ rThird := ReceiverResultReg.
+ (self register: ReceiverResultReg isInMask: self liveRegisters) ifTrue:
+ [ self ssAllocateRequiredReg: ReceiverResultReg ] ]
+ ifFalse: [ rThird := self allocateRegisterNotConflictingWith: topRegistersMask ].
+ topRegistersMask := topRegistersMask bitOr: (self registerMaskFor: rThird) ].
+
+ rTop ifNil: [
+ rTop := self allocateRegisterNotConflictingWith: topRegistersMask.
+ topRegistersMask := topRegistersMask bitOr: (self registerMaskFor: rTop) ].
+
+ rNext ifNil: [ rNext := self allocateRegisterNotConflictingWith: topRegistersMask ].
+
+ (rTop = ReceiverResultReg or: [rNext = ReceiverResultReg or: [rThird = ReceiverResultReg and: [ needsThirdRegUpdate ]]]) ifTrue:
+ [ optStatus isReceiverResultRegLive: false ].
+
+ ^ trinaryBlock value: rTop value: rNext value: rThird
+
+ !
Item was changed:
----- Method: StackToRegisterMappingCogit>>allocateTwoRegistersInto: (in category 'simulation stack') -----
allocateTwoRegistersInto: binaryBlock
| topRegistersMask rTop rNext |
+
topRegistersMask := 0.
+
self ssTop type = SSRegister ifTrue:
[ topRegistersMask := self registerMaskFor: (rTop := self ssTop register)].
(self ssValue: 1) type = SSRegister ifTrue:
[ topRegistersMask := topRegistersMask bitOr: (self registerMaskFor: (rNext := (self ssValue: 1) register))].
- (rTop notNil and: [rNext notNil]) ifTrue:
- [ ^ binaryBlock value: rTop value: rNext ].
+ rTop ifNil: [ rTop := self allocateRegisterNotConflictingWith: topRegistersMask ].
- rTop ifNotNil:
- [ rNext := backEnd availableRegisterOrNilFor: (self liveRegisters bitOr: topRegistersMask).
- rNext ifNil:
- [ rNext := backEnd availableRegisterOrNilFor: topRegistersMask.
- self assert: rNext notNil.
- self ssAllocateRequiredRegMask: rNext upThrough: simStackPtr - 1 ].
- ^ binaryBlock value: rTop value: rNext ].
+ rNext ifNil: [ rNext := self allocateRegisterNotConflictingWith: (self registerMaskFor: rTop) ].
- rNext ifNotNil:
- [ rTop := backEnd availableRegisterOrNilFor: (self liveRegisters bitOr: topRegistersMask).
- rTop ifNil:
- [ rTop := backEnd availableRegisterOrNilFor: topRegistersMask.
- self assert: rTop notNil.
- self ssAllocateRequiredRegMask: rTop upThrough: simStackPtr - 2 ].
- ^ binaryBlock value: rTop value: rNext ].
+ (rTop = ReceiverResultReg or: [rNext = ReceiverResultReg]) ifTrue:
+ [ optStatus isReceiverResultRegLive: false ].
- rTop := backEnd availableRegisterOrNilFor: self liveRegisters.
- topRegistersMask := rTop ifNotNil: [ self registerMaskFor: rTop ] ifNil: [0].
- rNext := backEnd availableRegisterOrNilFor: (self liveRegisters bitOr: topRegistersMask).
- (rTop notNil and: [ rNext notNil ]) ifTrue:
- [ ^ binaryBlock value: rTop value: rNext ].
+ ^ binaryBlock value: rTop value: rNext
- rTop ifNil: [ ^ self spillTwoRegistersInto: binaryBlock ].
- "rNext isNil. rTop is allocated"
- rNext := backEnd availableRegisterOrNilFor: topRegistersMask.
- self assert: rNext notNil.
- self ssAllocateRequiredRegMask: rNext upThrough: simStackPtr - 1.
- ^ binaryBlock value: rTop value: rNext
!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>freeRegisterNotConflictingWith: (in category 'simulation stack') -----
+ freeRegisterNotConflictingWith: registerMask
+ "Spill the closest register on stack not conflicting with registerMask.
+ Assertion Failure if registerMask has already all the registers"
+ <var: #desc type: #'CogSimStackEntry *'>
+ | reg index |
+ index := simSpillBase max: 0.
+ [reg isNil and: [index < simStackPtr] ] whileTrue:
+ [ | desc |
+ desc := self simStackAt: index.
+ desc type = SSRegister ifTrue:
+ [ (registerMask anyMask: (self registerMaskFor: desc register)) ifFalse:
+ [ reg := desc register ] ].
+ index := index + 1].
+ self assert: reg notNil.
+ self ssAllocateRequiredReg: reg.
+ ^reg!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genBinaryConstOpVarInlinePrimitive: (in category 'inline primitive generators') -----
genBinaryConstOpVarInlinePrimitive: prim
"Const op var version of binary inline primitives."
"SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution.
See EncoderForSistaV1's class comment and StackInterpreter>>#binaryInlinePrimitive:"
| ra val untaggedVal adjust |
+ ra := self allocateOneRegister.
- (ra := backEnd availableRegisterOrNilFor: self liveRegisters) ifNil:
- [self ssAllocateRequiredReg:
- (ra := optStatus isReceiverResultRegLive
- ifTrue: [Arg0Reg]
- ifFalse: [ReceiverResultReg])].
- ra = ReceiverResultReg ifTrue:
- [optStatus isReceiverResultRegLive: false].
self ssTop popToReg: ra.
self ssPop: 1.
val := self ssTop constant.
self ssPop: 1.
untaggedVal := val - objectMemory smallIntegerTag.
prim caseOf: {
"0 through 6, +, -, *, /, //, \\, quo:, SmallInteger op SmallInteger => SmallInteger, no overflow"
[0] -> [self AddCq: untaggedVal R: ra].
[1] -> [self MoveCq: val R: TempReg.
self SubR: ra R: TempReg.
objectRepresentation genAddSmallIntegerTagsTo: TempReg.
self MoveR: TempReg R: ra].
[2] -> [objectRepresentation genRemoveSmallIntegerTagsInScratchReg: ra.
self MoveCq: (objectMemory integerValueOf: val) R: TempReg.
self MulR: TempReg R: ra.
objectRepresentation genAddSmallIntegerTagsTo: ra].
"2016 through 2019, bitAnd:, bitOr:, bitXor, bitShift:, SmallInteger op SmallInteger => SmallInteger, no overflow"
"2032 through 2037, >, <, >=, <=. =, ~=, SmallInteger op SmallInteger => Boolean (flags?? then in jump bytecodes if ssTop is a flags value, just generate the instruction!!!!)"
[32] -> [ self CmpCq: val R: ra.
self genBinaryInlineComparison: JumpGreater opFalse: JumpLess destReg: ra ].
[33] -> [ self CmpCq: val R: ra.
self genBinaryInlineComparison: JumpLess opFalse: JumpGreater destReg: ra ].
[34] -> [ self CmpCq: val R: ra.
self genBinaryInlineComparison: JumpGreaterOrEqual opFalse: JumpLessOrEqual destReg: ra ].
[35] -> [ self CmpCq: val R: ra.
self genBinaryInlineComparison: JumpLessOrEqual opFalse: JumpGreaterOrEqual destReg: ra ].
[36] -> [ self CmpCq: val R: ra.
self genBinaryInlineComparison: JumpZero opFalse: JumpNonZero destReg: ra ].
[37] -> [ self CmpCq: val R: ra.
self genBinaryInlineComparison: JumpNonZero opFalse: JumpZero destReg: ra ].
"2064 through 2068, Pointer Object>>at:, Byte Object>>at:, Short16 Word Object>>at: LongWord32 Object>>at: Quad64Word Object>>at:. obj op 0-rel SmallInteger => oop"
[64] -> [objectRepresentation genConvertSmallIntegerToIntegerInReg: ra.
adjust := (objectMemory baseHeaderSize >> objectMemory shiftForWord) - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
adjust ~= 0 ifTrue: [ self AddCq: adjust R: ra. ].
self annotate: (self MoveCw: val R: TempReg) objRef: val.
self MoveXwr: ra R: TempReg R: ra].
[65] -> [objectRepresentation genConvertSmallIntegerToIntegerInReg: ra.
adjust := objectMemory baseHeaderSize - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
self AddCq: adjust R: ra.
self annotate: (self MoveCw: val R: TempReg) objRef: val.
self MoveXbr: ra R: TempReg R: ra]
}
otherwise: [^EncounteredUnknownBytecode].
self ssPushRegister: ra.
^0!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genBinaryVarOpConstInlinePrimitive: (in category 'inline primitive generators') -----
genBinaryVarOpConstInlinePrimitive: prim
"Var op const version of inline binary inline primitives."
"SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution.
See EncoderForSistaV1's class comment and StackInterpreter>>#binaryInlinePrimitive:"
| rr val untaggedVal |
- (rr := backEnd availableRegisterOrNilFor: self liveRegisters) ifNil:
- [self ssAllocateRequiredReg:
- (rr := optStatus isReceiverResultRegLive
- ifTrue: [Arg0Reg]
- ifFalse: [ReceiverResultReg])].
- rr = ReceiverResultReg ifTrue:
- [optStatus isReceiverResultRegLive: false].
val := self ssTop constant.
self ssPop: 1.
+ rr := self allocateOneRegister.
self ssTop popToReg: rr.
self ssPop: 1.
untaggedVal := val - objectMemory smallIntegerTag.
prim caseOf: {
"0 through 6, +, -, *, /, //, \\, quo:, SmallInteger op SmallInteger => SmallInteger, no overflow"
[0] -> [self AddCq: untaggedVal R: rr].
[1] -> [self SubCq: untaggedVal R: rr ].
[2] -> [self flag: 'could use MulCq:R'.
objectRepresentation genShiftAwaySmallIntegerTagsInScratchReg: rr.
self MoveCq: (objectMemory integerValueOf: val) R: TempReg.
self MulR: TempReg R: rr.
objectRepresentation genAddSmallIntegerTagsTo: rr].
"2016 through 2019, bitAnd:, bitOr:, bitXor, bitShift:, SmallInteger op SmallInteger => SmallInteger, no overflow"
"2032 through 2037, >, <, >=, <=. =, ~=, SmallInteger op SmallInteger => Boolean (flags?? then in jump bytecodes if ssTop is a flags value, just generate the instruction!!!!)
Here the comparison is reversed (cst on the left, reg on the right) so I inverted opTrue and opFalse"
[32] -> [ self CmpCq: val R: rr.
self genBinaryInlineComparison: JumpLess opFalse: JumpGreater destReg: rr ].
[33] -> [ self CmpCq: val R: rr.
self genBinaryInlineComparison: JumpGreater opFalse: JumpLess destReg: rr ].
[34] -> [ self CmpCq: val R: rr.
self genBinaryInlineComparison: JumpLessOrEqual opFalse: JumpGreaterOrEqual destReg: rr ].
[35] -> [ self CmpCq: val R: rr.
self genBinaryInlineComparison: JumpGreaterOrEqual opFalse: JumpLessOrEqual destReg: rr ].
[36] -> [ self CmpCq: val R: rr.
self genBinaryInlineComparison: JumpNonZero opFalse: JumpZero destReg: rr ].
[37] -> [ self CmpCq: val R: rr.
self genBinaryInlineComparison: JumpZero opFalse: JumpNonZero destReg: rr ].
"2064 through 2068, Pointer Object>>at:, Byte Object>>at:, Short16 Word Object>>at: LongWord32 Object>>at: Quad64Word Object>>at:. obj op 0-rel SmallInteger => oop"
[64] -> [objectRepresentation genLoadSlot: (objectMemory integerValueOf: val) - 1 sourceReg: rr destReg: rr].
[65] -> [self MoveCq: (objectMemory integerValueOf: val) + objectMemory baseHeaderSize - 1 R: TempReg.
self MoveXbr: TempReg R: rr R: rr.
objectRepresentation genConvertIntegerToSmallIntegerInReg: rr]
}
otherwise: [^EncounteredUnknownBytecode].
self ssPushRegister: rr.
^0!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genBinaryVarOpVarInlinePrimitive: (in category 'inline primitive generators') -----
genBinaryVarOpVarInlinePrimitive: prim
"Var op var version of binary inline primitives."
"SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution.
See EncoderForSistaV1's class comment and StackInterpreter>>#binaryInlinePrimitive:"
| ra rr adjust |
self allocateTwoRegistersInto: [:rTop :rNext | ra := rTop. rr := rNext ].
- (rr = ReceiverResultReg or: [ra = ReceiverResultReg]) ifTrue: [ optStatus isReceiverResultRegLive: false ].
self ssTop popToReg: ra.
self ssPop: 1.
self ssTop popToReg: rr.
self ssPop: 1.
prim caseOf: {
"0 through 6, +, -, *, /, //, \\, quo:, SmallInteger op SmallInteger => SmallInteger, no overflow"
[0] -> [objectRepresentation genRemoveSmallIntegerTagsInScratchReg: ra.
self AddR: ra R: rr].
[1] -> [self SubR: ra R: rr.
objectRepresentation genAddSmallIntegerTagsTo: rr].
[2] -> [objectRepresentation genRemoveSmallIntegerTagsInScratchReg: rr.
objectRepresentation genShiftAwaySmallIntegerTagsInScratchReg: ra.
self MulR: ra R: rr.
objectRepresentation genAddSmallIntegerTagsTo: rr].
"2016 through 2019, bitAnd:, bitOr:, bitXor, bitShift:, SmallInteger op SmallInteger => SmallInteger, no overflow"
"2032 through 2037, >, <, >=, <=. =, ~=, SmallInteger op SmallInteger => Boolean (flags?? then in jump bytecodes if ssTop is a flags value, just generate the instruction!!!!)"
[32] -> [ self CmpR: rr R: ra.
self genBinaryInlineComparison: JumpGreater opFalse: JumpLess destReg: rr ].
[33] -> [ self CmpR: rr R: ra.
self genBinaryInlineComparison: JumpLess opFalse: JumpGreater destReg: rr ].
[34] -> [ self CmpR: rr R: ra.
self genBinaryInlineComparison: JumpGreaterOrEqual opFalse: JumpLessOrEqual destReg: rr ].
[35] -> [ self CmpR: rr R: ra.
self genBinaryInlineComparison: JumpLessOrEqual opFalse: JumpGreaterOrEqual destReg: rr ].
[36] -> [ self CmpR: rr R: ra.
self genBinaryInlineComparison: JumpZero opFalse: JumpNonZero destReg: rr ].
[37] -> [ self CmpR: rr R: ra.
self genBinaryInlineComparison: JumpNonZero opFalse: JumpZero destReg: rr ].
"2064 through 2068, Pointer Object>>at:, Byte Object>>at:, Short16 Word Object>>at: LongWord32 Object>>at: Quad64Word Object>>at:. obj op 0-rel SmallInteger => oop"
[64] -> [objectRepresentation genConvertSmallIntegerToIntegerInReg: ra.
adjust := (objectMemory baseHeaderSize >> objectMemory shiftForWord) - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
adjust ~= 0 ifTrue: [ self AddCq: adjust R: ra. ].
self MoveXwr: ra R: rr R: rr ].
[65] -> [objectRepresentation genConvertSmallIntegerToIntegerInReg: ra.
adjust := objectMemory baseHeaderSize - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
self AddCq: adjust R: ra.
self MoveXbr: ra R: rr R: rr.
objectRepresentation genConvertIntegerToSmallIntegerInReg: rr]
}
otherwise: [^EncounteredUnknownBytecode].
self ssPushRegister: rr.
^0!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genTrinaryInlinePrimitive: (in category 'inline primitive generators') -----
genTrinaryInlinePrimitive: prim
"Unary inline primitives."
"SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution.
See EncoderForSistaV1's class comment and StackInterpreter>>#trinaryInlinePrimitive:"
| ra1 ra2 rr adjust |
+ "The store check requires rr to be ReceiverResultReg"
+ self allocateThreeRegistersInto: [:rTop :rNext :rThird | ra2 := rTop. ra1 := rNext. rr := rThird ] thirdIsReceiver: prim = 0.
- (ra2 := backEnd availableRegisterOrNilFor: self liveRegisters) ifNil:
- [self ssAllocateRequiredReg: (ra2 := Arg1Reg)].
- (ra1 := backEnd availableRegisterOrNilFor: (self liveRegisters bitOr: (self registerMaskFor: ra2))) ifNil:
- [self ssAllocateRequiredReg: (ra1 := Arg0Reg)].
- prim = 0
- ifTrue:
- [rr := ReceiverResultReg.
- ((self ssValue: 2) type = SSRegister
- and: [(self ssValue: 2) register = ReceiverResultReg]) ifFalse:
- [self ssAllocateRequiredReg: rr]]
- ifFalse:
- [(rr := backEnd availableRegisterOrNilFor: (self liveRegisters bitOr: (self registerMaskFor: ra1 and: ra2))) ifNil:
- [self ssAllocateRequiredReg: (rr := ReceiverResultReg)].
- optStatus isReceiverResultRegLive: false].
self assert: (rr ~= ra1 and: [rr ~= ra2 and: [ra1 ~= ra2]]).
self ssTop popToReg: ra2.
self ssPop: 1.
self ssTop popToReg: ra1.
self ssPop: 1.
self ssTop popToReg: rr.
self ssPop: 1.
objectRepresentation genConvertSmallIntegerToIntegerInReg: ra1.
"Now: ra is the variable object, rr is long, TempReg holds the value to store."
prim caseOf: {
"0 - 1 pointerAt:put: and byteAt:Put:"
[0] -> [ adjust := (objectMemory baseHeaderSize >> objectMemory shiftForWord) - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
adjust ~= 0 ifTrue: [ self AddCq: adjust R: ra1. ].
self MoveR: ra2 Xwr: ra1 R: rr.
objectRepresentation genStoreCheckReceiverReg: rr valueReg: ra2 scratchReg: TempReg].
[1] -> [ objectRepresentation genConvertSmallIntegerToIntegerInReg: ra2.
adjust := objectMemory baseHeaderSize - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
self AddCq: adjust R: ra1.
self MoveR: ra2 Xbr: ra1 R: rr.
objectRepresentation genConvertIntegerToSmallIntegerInReg: ra2. ]
}
otherwise: [^EncounteredUnknownBytecode].
self ssPushRegister: ra2.
^0!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genUnaryInlinePrimitive: (in category 'inline primitive generators') -----
genUnaryInlinePrimitive: prim
"Unary inline primitives."
"SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution.
See EncoderForSistaV1's class comment and StackInterpreter>>#unaryInlinePrimitive:"
| rcvrReg resultReg |
+ rcvrReg := self allocateOneRegister.
+ resultReg := self allocateRegisterNotConflictingWith: (self registerMaskFor: rcvrReg).
- self ssTop type = SSRegister
- ifTrue: [rcvrReg := self ssTop register]
- ifFalse:
- [(rcvrReg := backEnd availableRegisterOrNilFor: self liveRegisters) ifNil:
- [self ssAllocateRequiredReg:
- (rcvrReg := optStatus isReceiverResultRegLive
- ifTrue: [Arg0Reg]
- ifFalse: [ReceiverResultReg])]].
- (resultReg := backEnd availableRegisterOrNilFor: (self liveRegisters bitOr: (self registerMaskFor: rcvrReg))) ifNil:
- [self ssAllocateRequiredReg: (resultReg := Arg1Reg)].
self ssTop popToReg: rcvrReg.
self ssPop: 1.
prim
caseOf: {
"00 unchecked class"
[1] -> "01 unchecked pointer numSlots"
[objectRepresentation
genGetNumSlotsOf: rcvrReg into: resultReg;
genConvertIntegerToSmallIntegerInReg: resultReg].
"02 unchecked pointer basicSize"
[3] -> "03 unchecked byte numBytes"
[objectRepresentation
genGetNumBytesOf: rcvrReg into: resultReg;
genConvertIntegerToSmallIntegerInReg: resultReg].
"04 unchecked short16Type format numShorts"
"05 unchecked word32Type format numWords"
"06 unchecked doubleWord64Type format numDoubleWords"
}
otherwise:
[^EncounteredUnknownBytecode]..
self ssPushRegister: resultReg.
^0!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>register:isInMask: (in category 'simulation stack') -----
+ register: reg isInMask: mask
+ <inline: true>
+ ^ mask anyMask: (self registerMaskFor: reg)!
Item was removed:
- ----- Method: StackToRegisterMappingCogit>>spillTwoRegistersInto: (in category 'simulation stack') -----
- spillTwoRegistersInto: binaryBlock
- "Any occurrences on the stack of the register must be
- flushed, and hence any values colder than them stack."
- <var: #desc type: #'CogSimStackEntry *'>
- | r1 r2 index |
- index := simSpillBase max: 0.
- [r1 notNil and: [r2 notNil and: [index < simStackPtr]]] whileTrue:
- [| desc |
- desc := self simStackAt: index.
- desc type = SSRegister ifTrue:
- [ r1
- ifNil: [r1 := desc register]
- ifNotNil: [r1 ~= desc register ifTrue:
- [r2 := desc register]]].
- index := index + 1].
- self assert: (r1 notNil and: [r2 notNil]).
- self ssAllocateRequiredReg: r1 and: r2.
- ^binaryBlock value: r1 value: r2!
Item was changed:
----- Method: StackToRegisterMappingCogit>>ssAllocatePreferredReg: (in category 'simulation stack') -----
ssAllocatePreferredReg: preferredReg
| preferredMask lastPreferred liveRegs |
lastPreferred := -1.
"compute live regs while noting the last occurrence of preferredReg.
If there are none free we must spill from simSpillBase to last occurrence."
preferredMask := (self registerMaskFor: preferredReg).
liveRegs := self registerMaskFor: TempReg and: FPReg and: SPReg.
(simSpillBase max: 0) to: simStackPtr do:
[:i|
liveRegs := liveRegs bitOr: (self simStackAt: i) registerMask.
(liveRegs bitAnd: preferredMask) ~= 0 ifTrue:
[lastPreferred := i]].
"If preferredReg is not live we can allocate it."
+ (self register: preferredReg isInMask: liveRegs) ifFalse:
- (liveRegs bitAnd: (self registerMaskFor: preferredReg)) = 0 ifTrue:
[^preferredReg].
"If any other is not live we can allocate it."
GPRegMin to: GPRegMax do:
[:reg|
+ (self register: reg isInMask: liveRegs) ifFalse:
- (liveRegs bitAnd: (self registerMaskFor: reg)) = 0 ifTrue:
[^reg]].
"All live, must spill"
self ssFlushTo: lastPreferred.
self assert: (self liveRegisters bitAnd: preferredMask) = 0.
^preferredReg!
More information about the Vm-dev
mailing list