VM Maker: VMMaker.oscog-eem.2424.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: VMMaker.oscog-eem.2424.mcz

commits-2
 
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2424.mcz

==================== Summary ====================

Name: VMMaker.oscog-eem.2424
Author: eem
Time: 25 July 2018, 6:16:31.742351 pm
UUID: 84c4eaef-c4f2-4d8e-85d8-01b8aebfa554
Ancestors: VMMaker.oscog-eem.2423

SistaRegisterAllocatingCogit.
Noise.  Commit an updated SistaCogitClone (which is auto generated on startup).  Fix the comment in syncCodeWithSistaCogit.

=============== Diff against VMMaker.oscog-eem.2423 ===============

Item was added:
+ ----- Method: SistaCogitClone>>decodePushIntegerLongBefore:in: (in category 'compile abstract instructions') -----
+ decodePushIntegerLongBefore: bcpc in: aMethodObj
+ <inline: true>
+ | distance upperByte |
+ distance := objectMemory fetchByte: bcpc - 1 ofObject: aMethodObj.
+ upperByte := objectMemory fetchByte: bcpc - 3 ofObject: aMethodObj.
+ upperByte > 127 ifTrue: [upperByte := upperByte - 256].
+ ^ (upperByte << 8) + distance.
+ !

Item was changed:
  ----- Method: SistaCogitClone>>genAtPutInlinePrimitive: (in category 'inline primitive generators') -----
  genAtPutInlinePrimitive: 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 needsStoreCheck |
  "The store check requires rr to be ReceiverResultReg"
- needsStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
- self
- allocateRegForStackTopThreeEntriesInto: [:rTop :rNext :rThird | ra2 := rTop. ra1 := rNext. rr := rThird ]
- thirdIsReceiver: (prim = 0 and: [ needsStoreCheck ]).
- 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."
- self flag: #TODO. "This is not really working as the immutability and store check needs to be present. "
  prim caseOf: {
+ "3000 pointerAt:put:
+ Mutable pointer object (Fixed sized or not) and not a context, Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)"
+ [0] -> [self genPointerAtPutMaybeContext: false storeCheck: false immutabilityCheck: false].
+ "3001 storeCheckPointerAt:put:
+ Mutable pointer object (Fixed sized or not) and not a context, Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)"
+ [1] -> [self genPointerAtPutMaybeContext: false storeCheck: true immutabilityCheck: false].
+ "3002 maybeContextPointerAt:put:
+ Mutable pointer object (Fixed sized or not), Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)"
+ [2] -> [self genPointerAtPutMaybeContext: true storeCheck: false immutabilityCheck: false].
+ "3003 maybeContextStoreCheckPointerAt:put:
+ Mutable pointer object (Fixed sized or not), Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)"
+ [3] -> [self genPointerAtPutMaybeContext: true storeCheck: true immutabilityCheck: false].
+ "3004 byteAt:put:
+ Mutable byte object, Smi, 8 bits unsigned Smi => arg2 (1-based, optimised if arg1 is a constant)"
+ [4] -> [self genByteAtPut].
- "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.
- "I added needsStoreCheck so if you initialize an array with a Smi such as 0 or a boolean you don't need the store check"
- needsStoreCheck ifTrue:
- [ self assert: needsFrame.
- objectRepresentation genStoreCheckReceiverReg: rr valueReg: ra2 scratchReg: TempReg inFrame: true] ].
- [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 added:
+ ----- Method: SistaCogitClone>>genBinaryAtConstInlinePrimitive: (in category 'inline primitive binary generators') -----
+ genBinaryAtConstInlinePrimitive: primIndex
+ "2064 pointerAt:
+ Pointer object (Fixed sized or not) and not a context, Smi =>  (1-based, optimised if arg1 is a constant)
+ 2065 maybeContextPointerAt:
+ Pointer object (Fixed sized or not), Smi =>  (1-based, optimised if arg1 is a constant)
+ 2066 byteAt:
+ byte object, Smi => 8 bits unsigned Smi (1-based, optimised if arg1 is a constant)
+ 2067 shortAt:
+ short object, Smi => 16 bits unsigned Smi (1-based, optimised if arg1 is a constant)
+ 2068 wordAt:
+ word object, Smi => 32 bits unsigned Smi (1-based, optimised if arg1 is a constant)
+ 2069 doubleWordAt:
+ double word object, Smi => 64 bits unsigned Smi or LargePositiveInteger (1-based, optimised if arg1 is a constant)"
+ | rr val zeroBasedIndex |
+ val := self ssTop constant.
+ rr := primIndex = 65
+ ifFalse: [self allocateRegForStackEntryAt: 1]
+ ifTrue: [self ssAllocateRequiredReg: ReceiverResultReg.
+ self voidReceiverResultRegContainsSelf.
+ ReceiverResultReg].
+ (self ssValue: 1) popToReg: rr.
+ self ssPop: 2.
+ zeroBasedIndex := (objectMemory integerValueOf: val) - 1.
+ primIndex caseOf: {
+ [64] -> [objectRepresentation genLoadSlot: zeroBasedIndex sourceReg: rr destReg: rr].
+ [65] -> [self ssAllocateRequiredReg: SendNumArgsReg.
+ ^self genPushMaybeContextSlotIndex: zeroBasedIndex].
+ [66] -> [self MoveMb: zeroBasedIndex + objectMemory baseHeaderSize r: rr R: rr.
+ objectRepresentation genConvertIntegerToSmallIntegerInReg: rr]
+ }
+ otherwise: [^EncounteredUnknownBytecode].
+ ^self ssPushRegister: rr!

Item was added:
+ ----- Method: SistaCogitClone>>genBinaryAtInlinePrimitive: (in category 'inline primitive binary generators') -----
+ genBinaryAtInlinePrimitive: primIndex
+ "2064 pointerAt:
+ Pointer object (Fixed sized or not) and not a context, Smi =>  (1-based, optimised if arg1 is a constant)
+ 2065 maybeContextPointerAt:
+ Pointer object (Fixed sized or not), Smi =>  (1-based, optimised if arg1 is a constant)
+ 2066 byteAt:
+ byte object, Smi => 8 bits unsigned Smi (1-based, optimised if arg1 is a constant)
+ 2067 shortAt:
+ short object, Smi => 16 bits unsigned Smi (1-based, optimised if arg1 is a constant)
+ 2068 wordAt:
+ word object, Smi => 32 bits unsigned Smi (1-based, optimised if arg1 is a constant)
+ 2069 doubleWordAt:
+ double word object, Smi => 64 bits unsigned Smi or LargePositiveInteger (1-based, optimised if arg1 is a constant)"
+ | ra rr adjust |
+ self allocateRegForStackTopTwoEntriesInto: [:rTop :rNext | ra := rTop. rr := rNext ].
+ self ssTop popToReg: ra.
+ self ssPop: 1.
+ self ssTop popToReg: rr.
+ self ssPop: 1.
+ primIndex caseOf: {
+ [64] -> [objectRepresentation genConvertSmallIntegerToIntegerInReg: ra.
+ adjust := (objectMemory baseHeaderSize >> objectMemory shiftForWord) - 1.
+ adjust ~= 0 ifTrue: [ self AddCq: adjust R: ra. ].
+ self MoveXwr: ra R: rr R: rr ].
+ [66] -> [objectRepresentation genConvertSmallIntegerToIntegerInReg: ra.
+ adjust := objectMemory baseHeaderSize - 1.
+ self AddCq: adjust R: ra.
+ self MoveXbr: ra R: rr R: rr.
+ objectRepresentation genConvertIntegerToSmallIntegerInReg: rr].
+ }
+ otherwise: [^EncounteredUnknownBytecode].
+ ^self ssPushRegister: rr!

Item was added:
+ ----- Method: SistaCogitClone>>genBinaryCompInlinePrimitive: (in category 'inline primitive binary generators') -----
+ genBinaryCompInlinePrimitive: primIndex
+ "2032 >
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2033 <
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2034 >=
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2035 <=
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2036 =
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2037 ~=
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2038 rawEqualsEquals:
+ not a forwarder, not a forwarder => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2039 rawNotEqualsEquals:
+ not a forwarder, not a forwarder => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)"
+ |resultReg otherReg opTrue opFalse invertedOpTrue invertedOpFalse|
+ self assert: (primIndex between: 32 and: 39).
+ primIndex caseOf: {
+ [32] -> [opTrue := JumpGreater. opFalse := JumpLessOrEqual. invertedOpTrue := JumpLess. invertedOpFalse := JumpGreaterOrEqual].
+ [33] -> [opTrue := JumpLess. opFalse := JumpGreaterOrEqual. invertedOpTrue := JumpGreater. invertedOpFalse := JumpLessOrEqual].
+ [34] -> [opTrue := JumpGreaterOrEqual. opFalse := JumpLess. invertedOpTrue := JumpLessOrEqual. invertedOpFalse := JumpGreater].
+ [35] -> [opTrue := JumpLessOrEqual. opFalse := JumpGreater. invertedOpTrue := JumpGreaterOrEqual. invertedOpFalse := JumpLess].
+ [36] -> [opTrue := JumpZero. opFalse := JumpNonZero. invertedOpTrue := JumpZero. invertedOpFalse := JumpNonZero].
+ [37] -> [opTrue := JumpNonZero. opFalse := JumpZero. invertedOpTrue := JumpNonZero. invertedOpFalse := JumpZero].
+ [38] -> [opTrue := JumpZero. opFalse := JumpNonZero. invertedOpTrue := JumpZero. invertedOpFalse := JumpNonZero].
+ [39] -> [opTrue := JumpNonZero. opFalse := JumpZero. invertedOpTrue := JumpNonZero. invertedOpFalse := JumpZero].
+ }.
+ "Gen comparison"
+ self ssTop type = SSConstant
+ ifTrue: [resultReg := self allocateRegForStackEntryAt: 1.
+ (self ssValue: 1) popToReg: resultReg.
+ self genCmpConstant: self ssTop constant R: resultReg.
+ self ssPop: 2.
+ self genBinaryInlineComparison: opTrue opFalse: opFalse destReg: resultReg.
+ ^self ssPushRegister: resultReg].
+ (self ssValue: 1) type = SSConstant
+ ifTrue: [resultReg := self allocateRegForStackEntryAt: 0.
+ self ssTop popToReg: resultReg.
+ self genCmpConstant: (self ssValue: 1) constant R: resultReg.
+ self ssPop: 2.
+ self genBinaryInlineComparison: invertedOpTrue opFalse: invertedOpFalse destReg: resultReg.
+ ^self ssPushRegister: resultReg].
+ otherReg := self allocateRegForStackEntryAt: 0.
+ self ssTop popToReg: otherReg.
+ resultReg := self allocateRegForStackEntryAt: 1 notConflictingWith: (self registerMaskFor: otherReg).
+ (self ssValue: 1) popToReg: resultReg.
+ self CmpR: otherReg R: resultReg.
+ self ssPop: 2.
+ self genBinaryInlineComparison: opTrue opFalse: opFalse destReg: resultReg.
+ ^self ssPushRegister: resultReg
+
+ !

Item was added:
+ ----- Method: SistaCogitClone>>genBinaryConstOpVarSmiInlinePrimitive: (in category 'inline primitive binary generators') -----
+ genBinaryConstOpVarSmiInlinePrimitive: primIndex
+ | ra val untaggedVal |
+ ra := self allocateRegForStackEntryAt: 0.
+ self ssTop popToReg: ra.
+ self ssPop: 1.
+ val := self ssTop constant.
+ self ssPop: 1.
+ untaggedVal := val - objectMemory smallIntegerTag.
+ primIndex caseOf: {
+ "2000 +
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)"
+ [0] -> [self AddCq: untaggedVal R: ra].
+ "2001 -
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)"
+ [1] -> [self MoveCq: val R: TempReg.
+ self SubR: ra R: TempReg.
+ objectRepresentation genAddSmallIntegerTagsTo: TempReg.
+ self MoveR: TempReg R: ra].
+ "2002 *
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)"
+ [2] -> [objectRepresentation genShiftAwaySmallIntegerTagsInScratchReg: ra.
+ self MoveCq: untaggedVal R: TempReg.
+ self MulR: TempReg R: ra.
+ objectRepresentation genSetSmallIntegerTagsIn: ra].
+
+ "2016 bitAnd:
+ Smi, Smi => Smi (optimised if one operand is a constant)"
+ [16] -> [ self AndCq: val R: ra ].
+ "2017 bitOr:
+ Smi, Smi => Smi (optimised if one operand is a constant)"
+ [17] -> [ self OrCq: val R: ra ].
+ "2018 bitXor:
+ Smi, Smi => Smi (optimised if one operand is a constant)"
+ [18] -> [ self XorCw: untaggedVal R: ra. ].
+ }
+ otherwise: [^EncounteredUnknownBytecode].
+ self ssPushRegister: ra.
+ ^0!

Item was added:
+ ----- Method: SistaCogitClone>>genBinaryInlinePrimitive: (in category 'inline primitive binary generators') -----
+ genBinaryInlinePrimitive: primIndex
+ "Bulk comments: each sub-method has its own comment with the specific case.
+ 2000 +
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)
+ 2001 -
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)
+ 2002 *
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)
+ 2003 /
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)
+ 2004 //
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)
+ 2005 \
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)
+ 2006 quo:
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)
+ 2016 bitAnd:
+ Smi, Smi => Smi (optimised if one operand is a constant)
+ 2017 bitOr:
+ Smi, Smi => Smi (optimised if one operand is a constant)
+ 2018 bitXor:
+ Smi, Smi => Smi (optimised if one operand is a constant)
+ 2019 bitShiftLeft:
+ Smi greater or equal to 0, Smi greater or equal to 0 => Smi (no overflow, optimised if arg1 is a constant)
+ 2020 bitShiftRight:
+ Smi, Smi greater or equal to 0 => Smi (optimised if arg1 is a constant)
+ 2032 >
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2033 <
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2034 >=
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2035 <=
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2036 =
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2037 ~=
+ Smi, Smi => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2038 rawEqualsEquals:
+ not a forwarder, not a forwarder => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2039 rawNotEqualsEquals:
+ not a forwarder, not a forwarder => Boolean (optimised if one operand is a constant, Pipelined with ifTrue:ifFalse:)
+ 2048 rawNew:
+ literal which is a fixed-sized behavior, Smi => instance of receiver, fields nilled out (optimised if arg1 is a constant)
+ 2049 rawNewNoInit:
+ literal which is a fixed-sized behavior, Smi => instance of receiver (Fields of returned value contain undefined data, optimised if arg1 is a constant)
+ 2064 pointerAt:
+ Pointer object (Fixed sized or not) and not a context, Smi =>  (1-based, optimised if arg1 is a constant)
+ 2065 maybeContextPointerAt:
+ Pointer object (Fixed sized or not), Smi =>  (1-based, optimised if arg1 is a constant)
+ 2066 byteAt:
+ byte object, Smi => 8 bits unsigned Smi (1-based, optimised if arg1 is a constant)
+ 2067 shortAt:
+ short object, Smi => 16 bits unsigned Smi (1-based, optimised if arg1 is a constant)
+ 2068 wordAt:
+ word object, Smi => 32 bits unsigned Smi (1-based, optimised if arg1 is a constant)
+ 2069 doubleWordAt:
+ double word object, Smi => 64 bits unsigned Smi or LargePositiveInteger (1-based, optimised if arg1 is a constant)"
+ (primIndex <= 18 and: [primIndex <= 2 or: [primIndex > 6]])  ifTrue:
+ [self ssTop type = SSConstant
+ ifTrue: [^self genBinaryVarOpConstSmiInlinePrimitive: primIndex].
+ (self ssValue: 1) type = SSConstant
+ ifTrue: [^self genBinaryConstOpVarSmiInlinePrimitive: primIndex].
+ ^self genBinaryVarOpVarSmiInlinePrimitive: primIndex].
+ primIndex <= 6 ifTrue: [^self genDivInlinePrimitive: primIndex].
+ primIndex = 19 ifTrue: [^self genBinarySmiBitShiftLeftInlinePrimitive].
+ primIndex = 20 ifTrue: [^self genBinarySmiBitShiftRightInlinePrimitive].
+ primIndex < 32 ifTrue: [^EncounteredUnknownBytecode].
+ primIndex <= 39 ifTrue: [^self genBinaryCompInlinePrimitive: primIndex].
+ primIndex < 48 ifTrue: [^EncounteredUnknownBytecode].
+ primIndex <= 49 ifTrue: [^self genBinaryNewInlinePrimitive: primIndex].
+ primIndex < 64 ifTrue: [^EncounteredUnknownBytecode].
+ primIndex <= 69 ifTrue:
+ [self ssTop type = SSConstant
+ ifTrue: [^self genBinaryAtConstInlinePrimitive: primIndex].
+ ^self genBinaryAtInlinePrimitive: primIndex].
+ ^EncounteredUnknownBytecode!

Item was added:
+ ----- Method: SistaCogitClone>>genBinaryNewInlinePrimitive: (in category 'inline primitive binary generators') -----
+ genBinaryNewInlinePrimitive: primIndex
+ "2048 rawNew:
+ literal which is a variable-sized behavior, Smi => instance of receiver, fields nilled/zeroed out (optimised if arg1 is a constant)
+ 2049 rawNewNoInit:
+ literal which is a variable-sized behavior, Smi => instance of receiver (Fields of returned value contain undefined data, optimised if arg1 is a constant)"
+ | resultReg classObj classFormat argInt |
+
+ "Assertion"
+ (self ssValue: 1) type = SSConstant ifFalse: [^UnimplementedOperation].
+
+ "It would be nice to deal with variable-sized allocation on non-constant.
+ We need to see, however, than inlined allocation cannot deal with large allocations (i.e.
+ allocation directly in old space, > 65k currently. So Scorch still needs to perform range analysis
+ or generate 2 paths at the bytecode level in this case."
+ self ssTop type = SSConstant ifFalse: [^UnimplementedOperation].
+
+ classObj := (self ssValue: 1) constant.
+ self assert: (objectMemory isNonImmediate: classObj).
+ self assert: (coInterpreter objCouldBeClassObj: classObj).
+ self deny: (objectMemory isFixedSizePointerFormat: (objectMemory instSpecOfClassFormat: (objectMemory formatOfClass: classObj))).
+ objectMemory classTagForClass: classObj. "Ensure Behavior hash"
+
+ "Actual code"
+ resultReg := self allocateRegNotConflictingWith: 0.
+ classFormat := objectMemory instSpecOfClassFormat: (objectMemory formatOfClass: classObj).
+ argInt := objectMemory integerValueOf: self ssTop constant.
+ self ssPop: 2.
+ self ssPushRegister: resultReg.
+ (classFormat = objectMemory arrayFormat or: [classFormat = objectMemory indexablePointersFormat]) ifTrue:
+ [^objectRepresentation genGetInstanceOfPointerClass: classObj into: resultReg initializingIf: primIndex = 48 numVariableSlots: argInt].
+ (classFormat = objectMemory firstByteFormat) ifTrue:
+ [^objectRepresentation genGetInstanceOfByteClass: classObj into: resultReg initializingIf: primIndex = 48 numBytes: argInt].
+ ^UnimplementedOperation!

Item was added:
+ ----- Method: SistaCogitClone>>genBinarySmiBitShiftLeftInlinePrimitive (in category 'inline primitive binary generators') -----
+ genBinarySmiBitShiftLeftInlinePrimitive
+ "2019 bitShiftLeft:
+ Smi greater or equal to 0, Smi greater or equal to 0 => Smi (no overflow, optimised if arg1 is a constant)"
+ | rr ra |
+ rr := self allocateRegForStackEntryAt: 1.
+ (self ssValue: 1) popToReg: rr.
+ objectRepresentation genRemoveSmallIntegerTagsInScratchReg: rr.
+ self ssTop type = SSConstant
+ ifTrue: [self LogicalShiftLeftCq: (objectMemory integerValueOf: self ssTop constant) R: rr]
+ ifFalse: [ra := self allocateRegForStackEntryAt: 0 notConflictingWith: (self registerMaskFor: rr).
+ self ssTop popToReg: ra.
+ objectRepresentation genConvertSmallIntegerToIntegerInReg: ra.
+ self LogicalShiftLeftR: ra R: rr.].
+ objectRepresentation genAddSmallIntegerTagsTo: rr.
+ self ssPop: 2.
+ ^self ssPushRegister: rr
+ !

Item was added:
+ ----- Method: SistaCogitClone>>genBinarySmiBitShiftRightInlinePrimitive (in category 'inline primitive binary generators') -----
+ genBinarySmiBitShiftRightInlinePrimitive
+ "2019 bitShiftLeft:
+ Smi greater or equal to 0, Smi greater or equal to 0 => Smi (no overflow, optimised if arg1 is a constant)"
+ | rr ra |
+ rr := self allocateRegForStackEntryAt: 1.
+ (self ssValue: 1) popToReg: rr.
+ self ssTop type = SSConstant
+ ifTrue: [self ArithmeticShiftRightCq: (objectMemory integerValueOf: self ssTop constant) R: rr]
+ ifFalse: [ra := self allocateRegForStackEntryAt: 0 notConflictingWith: (self registerMaskFor: rr).
+ self ssTop popToReg: ra.
+ objectRepresentation genConvertSmallIntegerToIntegerInReg: ra.
+ self ArithmeticShiftRightR: ra R: rr].
+ objectRepresentation genClearAndSetSmallIntegerTagsIn: rr.
+ self ssPop: 2.
+ ^self ssPushRegister: rr!

Item was added:
+ ----- Method: SistaCogitClone>>genBinaryVarOpConstSmiInlinePrimitive: (in category 'inline primitive binary generators') -----
+ genBinaryVarOpConstSmiInlinePrimitive: primIndex
+ | rr val untaggedVal |
+ self assert: primIndex <= 18.
+ val := self ssTop constant.
+ self ssPop: 1.
+ rr := self allocateRegForStackEntryAt: 0.
+ self ssTop popToReg: rr.
+ self ssPop: 1.
+ untaggedVal := val - objectMemory smallIntegerTag.
+ primIndex caseOf: {
+ "2000 +
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)"
+ [0] -> [self AddCq: untaggedVal R: rr].
+ "2001 -
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)"
+ [1] -> [self SubCq: untaggedVal R: rr ].
+ "2002 *
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)"
+ [2] -> [self flag: 'could use MulCq:R'.
+ objectRepresentation genShiftAwaySmallIntegerTagsInScratchReg: rr.
+ self MoveCq: untaggedVal R: TempReg.
+ self MulR: TempReg R: rr.
+ objectRepresentation genSetSmallIntegerTagsIn: rr].
+
+ "2016 bitAnd:
+ Smi, Smi => Smi (optimised if one operand is a constant)"
+ [16] -> [ self AndCq: val R: rr ].
+ "2017 bitOr:
+ Smi, Smi => Smi (optimised if one operand is a constant)"
+ [17] -> [ self OrCq: val R: rr ].
+ "2018 bitXor:
+ Smi, Smi => Smi (optimised if one operand is a constant)"
+ [18] -> [ self flag: 'could use XorCq:'.
+ self XorCw: untaggedVal R: rr. ]
+
+ }
+ otherwise: [^EncounteredUnknownBytecode].
+ self ssPushRegister: rr.
+ ^0!

Item was added:
+ ----- Method: SistaCogitClone>>genBinaryVarOpVarSmiInlinePrimitive: (in category 'inline primitive binary generators') -----
+ genBinaryVarOpVarSmiInlinePrimitive: primIndex
+ | ra rr |
+ self allocateRegForStackTopTwoEntriesInto: [:rTop :rNext | ra := rTop. rr := rNext ].
+ self ssTop popToReg: ra.
+ self ssPop: 1.
+ self ssTop popToReg: rr.
+ self ssPop: 1.
+ primIndex caseOf: {
+ "2000 +
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)"
+ [0] -> [objectRepresentation genRemoveSmallIntegerTagsInScratchReg: ra.
+ self AddR: ra R: rr].
+ "2001 -
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)"
+ [1] -> [self SubR: ra R: rr.
+ objectRepresentation genAddSmallIntegerTagsTo: rr].
+ "2002 *
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant)"
+ [2] -> [self genShiftAwaySmallIntegerTagsInScratchReg: rr.
+ self genRemoveSmallIntegerTagsInScratchReg: ra.
+ self MulR: ra R: rr.
+ self genSetSmallIntegerTagsIn: rr].
+
+ "2016 bitAnd:
+ Smi, Smi => Smi (optimised if one operand is a constant)"
+ [16] -> [ self AndR: ra R: rr ].
+ "2017 bitOr:
+ Smi, Smi => Smi (optimised if one operand is a constant)"
+ [17] -> [ self OrR: ra R: rr ].
+ "2018 bitXor:
+ Smi, Smi => Smi (optimised if one operand is a constant)"
+ [18] -> [objectRepresentation genRemoveSmallIntegerTagsInScratchReg: ra.
+ self XorR: ra R: rr. ]
+ }
+ otherwise: [^EncounteredUnknownBytecode].
+ self ssPushRegister: rr.
+ ^0!

Item was added:
+ ----- Method: SistaCogitClone>>genByteAtPut (in category 'inline primitive generators') -----
+ genByteAtPut
+ | ra1 ra2 rr adjust |
+ self
+ allocateRegForStackTopThreeEntriesInto: [:rTop :rNext :rThird | ra2 := rTop. ra1 := rNext. rr := rThird ]
+ thirdIsReceiver: 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.
+ adjust := objectMemory baseHeaderSize - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
+ objectRepresentation genConvertSmallIntegerToIntegerInReg: ra1.
+ objectRepresentation genConvertSmallIntegerToIntegerInReg: ra2.
+ self AddCq: adjust R: ra1.
+ self MoveR: ra2 Xbr: ra1 R: rr.
+ objectRepresentation genConvertIntegerToSmallIntegerInReg: ra2.
+ ^self ssPushRegister: ra2!

Item was added:
+ ----- Method: SistaCogitClone>>genByteAtPutImmutabilityCheck (in category 'mapped inline primitive generators') -----
+ genByteAtPutImmutabilityCheck
+ | ra1 ra2 rr adjust mutableJump immutabilityFailure indexIsCst |
+ <var: #mutableJump type: #'AbstractInstruction *'>
+ <var: #immutabilityFailure type: #'AbstractInstruction *'>
+ "Assumes rr is not a context and no store check is needed"
+ indexIsCst := (self ssValue: 1) type = SSConstant.
+ rr := ReceiverResultReg.
+ ra1 := TempReg.
+ ra2 := ClassReg.
+ self voidReceiverResultRegContainsSelf.
+ self ssFlushTo: simStackPtr - 1. "we use top value immediately after, so it does not require flush"
+ self ssTop popToReg: ra2.
+ adjust := objectMemory baseHeaderSize - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
+ indexIsCst
+ ifFalse:
+ [(self ssValue: 1) popToReg: ra1.
+ objectRepresentation genConvertSmallIntegerToIntegerInReg: ra1.
+ self AddCq: adjust R: ra1]
+ ifTrue: [self MoveCq: (objectMemory integerValueOf: (self ssValue: 1) constant) + adjust R: ra1].
+ (self ssValue: 2) popToReg: rr.
+ self ssPop: 3.
+ self ssPushRegister: ra2.
+
+ "Everything is flushed except returned value. All regs are unused except rr ra1 ra2"
+ mutableJump := self genJumpMutable: rr scratchReg: Arg0Reg.
+ self PushR: ra2. "flush sim stack top"
+ self SubCq: 1 + adjust R: ra1. "index 0-relative for trampoline, ra1 unused afterwards"
+ objectRepresentation genVarIndexCallStoreTrampoline.
+ self PopR: ra2. "restore sim stack top"
+ immutabilityFailure := self Jump: 0.
+
+ mutableJump jmpTarget: (self MoveR: ra2 R: Arg0Reg).
+ objectRepresentation genConvertSmallIntegerToIntegerInReg: Arg0Reg.
+ self MoveR: Arg0Reg Xbr: ra1 R: rr.
+
+ immutabilityFailure jmpTarget: self Label.
+ ^0!

Item was changed:
  ----- Method: SistaCogitClone>>genByteEqualsInlinePrimitive: (in category 'inline primitive generators') -----
  genByteEqualsInlinePrimitive: prim
 
  "3021 Byte Object >> equals:length:
  The receiver and the arguments are both byte objects and have both the same size (length in bytes).
  The length argument is a smallinteger.
  Answers true if all fields are equal, false if not.
  Comparison is bulked to word comparison."
 
  "Overview:
  1. The primitive is called like that: [byteObj1 equals: byteObj2 length: length].
    In the worst case we use 5 registers including TempReg
  and we produce a loop bulk comparing words.
  2. The common case is a comparison against a cst: [byteString = 'foo'].
  which produces in Scorch [byteString equals: 'foo' length: 3].
  We try to generate fast code for this case with 3 heuristics:
  - specific fast code if len is a constant
  - unroll the loop if len < 2 * wordSize
  - compile-time reads if str1 or str2 is a constant and loop is unrolled.
  We use 3 registers including TempReg in the common case.
  We could use 1 less reg if the loop is unrolled, the instr is followed by a branch
  AND one operand is a constant, but this is complicated enough.
  3. We ignore the case where all operands are constants
  (We assume Scorch simplifies it, it works but it is not optimised)"
 
  | str1Reg str2Reg lenReg extraReg jmp jmp2 needjmpZeroSize needLoop unroll jmpZeroSize instr lenCst mask |
  <var: #jmp type: #'AbstractInstruction *'>
  <var: #instr type: #'AbstractInstruction *'>
  <var: #jmp2 type: #'AbstractInstruction *'>
  <var: #jmpZeroSize type: #'AbstractInstruction *'>
 
  "--- quick path for empty string---"
  "This path does not allocate registers and right shift on negative int later in the code.
  Normally this is resolved by Scorch but we keep it for correctness and consistency"
  self ssTop type = SSConstant ifTrue:
  [ lenCst := objectMemory integerValueOf: self ssTop constant.
   lenCst = 0 ifTrue: [ self ssPop: 3. self ssPushConstant: objectMemory trueObject. ^ 0 ] ].
 
  "--- Allocating & loading registers --- "
  needLoop := (self ssTop type = SSConstant and: [ lenCst <= (objectMemory wordSize * 2) ]) not.
  unroll := needLoop not and: [lenCst > objectMemory wordSize ].
  needLoop
  ifTrue:
+ [ self assert: self ssTop spilled not.
+  str1Reg := self allocateRegForStackEntryAt: 1 notConflictingWith: self emptyRegisterMask.
- [ str1Reg := self allocateRegForStackEntryAt: 1 notConflictingWith: self emptyRegisterMask.
   str2Reg := self allocateRegForStackEntryAt: 2 notConflictingWith: (self registerMaskFor: str1Reg).
+  lenReg := self allocateRegForStackEntryAt: 0 notConflictingWith: (self registerMaskFor: str1Reg and: str2Reg).
-  lenReg := self allocateRegForStackEntryAt: 0 notConflictingWith: (self registerMaskFor:str1Reg and: str2Reg).
   (self ssValue: 1) popToReg: str1Reg.
   (self ssValue: 2) popToReg: str2Reg.
   extraReg := self allocateRegNotConflictingWith: (self registerMaskFor: str1Reg and: str2Reg and: lenReg)]
  ifFalse:
  [ mask := self emptyRegisterMask.
   (self ssValue: 1) type = SSConstant ifFalse:
  [ str1Reg := self allocateRegForStackEntryAt: 1 notConflictingWith: mask.
   (self ssValue: 1) popToReg: str1Reg.
   mask := mask bitOr: (self registerMaskFor: str1Reg) ].
   (self ssValue: 2) type = SSConstant ifFalse:
  [ str2Reg := self allocateRegForStackEntryAt: 2 notConflictingWith: mask.
   (self ssValue: 2) popToReg: str2Reg.
   mask := mask bitOr: (self registerMaskFor: str2Reg) ].
   extraReg := self allocateRegNotConflictingWith: mask].
 
  "--- Loading LenReg (or statically resolving it) --- "
  "LenReg is loaded with (lenInBytes + objectMemory baseHeaderSize - 1 >> shiftForWord)
  LenReg is the index for the last word to compare with MoveXwr:r:R:.
  The loop iterates from LenReg to first word of ByteObj"
  self ssTop type = SSConstant
  ifTrue: "common case, str = 'foo'. We can precompute lenReg."
  [ lenCst := lenCst + objectMemory baseHeaderSize - 1 >> objectMemory shiftForWord.
   needLoop ifTrue: [self MoveCq: lenCst R: lenReg ].
   needjmpZeroSize := false]
  ifFalse: "uncommon case, str = str2. lenReg in word computed at runtime."
  [ self ssTop popToReg: lenReg.
   objectRepresentation genConvertSmallIntegerToIntegerInReg: lenReg.
   self CmpCq: 0 R: lenReg.
   jmpZeroSize := self JumpZero: 0.
   needjmpZeroSize := true.
   self AddCq: objectMemory baseHeaderSize - 1 R: lenReg.
   self ArithmeticShiftRightCq: objectMemory shiftForWord R: lenReg ].
 
  "--- Comparing the strings --- "
  "LenReg has the index of the last word to read (unless no loop).
  We decrement it to adjust -1 (0 in 64 bits) while comparing"
  needLoop
  ifTrue:
  [instr := self MoveXwr: lenReg R: str1Reg R: extraReg.
  self MoveXwr: lenReg R: str2Reg R: TempReg.
  self CmpR: extraReg R: TempReg.
  jmp := self JumpNonZero: 0. "then string are not equal (jmp target)"
  self AddCq: -1 R: lenReg.
  self CmpCq: (objectMemory baseHeaderSize >> objectMemory shiftForWord) - 1 R: lenReg. "first word of ByteObj, stop looping."
  self JumpNonZero: instr]
  ifFalse: "Common case, only 1 or 2 word to check: no lenReg allocation, cst micro optimisations"
  [self genByteEqualsInlinePrimitiveCmp: str1Reg with: str2Reg scratch1: extraReg scratch2: TempReg field: 0.
  jmp := self JumpNonZero: 0. "then string are not equal (jmp target)"
  unroll ifTrue: "unrolling more than twice generate more instructions than the loop so we don't do it"
  [self genByteEqualsInlinePrimitiveCmp: str1Reg with: str2Reg scratch1: extraReg scratch2: TempReg field: 1.
  jmp2 := self JumpNonZero: 0. "then string are not equal (jmp target)"]].
  needjmpZeroSize ifTrue: [ jmpZeroSize jmpTarget: self Label ].
  "fall through, strings are equal"
 
  "--- Pushing the result or pipelining a branch --- "
  self ssPop: 3.
  self genByteEqualsInlinePrimitiveResult: jmp returnReg: extraReg.
  unroll ifTrue: [jmp2 jmpTarget: jmp getJmpTarget].
  ^0!

Item was added:
+ ----- Method: SistaCogitClone>>genCallMappedInlinedPrimitive (in category 'mapped inline primitive generators') -----
+ genCallMappedInlinedPrimitive
+ "SistaV1: 236 11101100 iiiiiiii callMappedInlinedPrimitive"
+ ^ self genMappedInlinePrimitive: byte1!

Item was changed:
  ----- Method: SistaCogitClone>>genCallPrimitiveBytecode (in category 'bytecode generators') -----
  genCallPrimitiveBytecode
  "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>>#inlinePrimitiveBytecode:"
  | prim primSet |
  byte2 < 128 ifTrue:
  [^bytecodePC = initialPC
  ifTrue: [0]
  ifFalse: [EncounteredUnknownBytecode]].
  prim := byte2 - 128 << 8 + byte1.
  primSet := prim >> 13 bitAnd: 3.
  prim := prim bitAnd: 8191.
  LowcodeVM
  ifTrue:
  [
  primSet = 1 ifTrue: [
  prim < 1000 ifTrue:
  [^self genLowcodeNullaryInlinePrimitive: prim].
 
  prim < 2000 ifTrue:
  [^self genLowcodeUnaryInlinePrimitive: prim - 1000].
 
  prim < 3000 ifTrue:
  [^ self genLowcodeBinaryInlinePrimitive: prim - 2000].
 
  prim < 4000 ifTrue:
  [^self genLowcodeTrinaryInlinePrimitive: prim - 3000].
  ]
  ].
 
  self assert: primSet = 0.
 
+ ^ self genSistaInlinePrimitive: prim!
- prim < 1000 ifTrue:
- [^self genNullaryInlinePrimitive: prim].
-
- prim < 2000 ifTrue:
- [^self genUnaryInlinePrimitive: prim - 1000].
-
- prim < 3000 ifTrue:
- [self ssTop type = SSConstant ifTrue:
- [^self genBinaryVarOpConstInlinePrimitive: prim - 2000].
- (self ssValue: 1) type = SSConstant ifTrue:
- [^self genBinaryConstOpVarInlinePrimitive: prim - 2000].
- ^self genBinaryVarOpVarInlinePrimitive: prim - 2000].
-
- prim < 4000 ifTrue:
- [^self genTrinaryInlinePrimitive: prim - 3000].
-
- prim < 5000 ifTrue:
- [^self genQuaternaryInlinePrimitive: prim - 4000].
-
- prim < 6000 ifTrue:
- [^self genQuinaryInlinePrimitive: prim - 5000].
-
- ^EncounteredUnknownBytecode!

Item was added:
+ ----- Method: SistaCogitClone>>genDirectCall (in category 'mapped inline primitive generators') -----
+ genDirectCall
+ "250 directCall
+ literal index of the method to call on top of stack =>  (variable number of parameters)"
+ | newMethod newMethodHeader newMethodArgCount sendTable annotation litIndex |
+ self assert: (self ssTop type = SSConstant and: [objectMemory isCompiledMethod: self ssTop constant]).
+ litIndex := objectMemory integerValueOf: self ssTop constant.
+ newMethod := self getLiteral: litIndex.
+ self ssPop: 1.
+ self flag: #TODO. "One needs to finish the implementation with the annotation and the sendTable"
+ sendTable := 1. "directCallSendTable"
+ annotation := 1. "directCallAnnotation"
+ newMethodHeader := self rawHeaderOf: newMethod.
+ newMethodArgCount := self argumentCountOfMethodHeader: methodHeader.
+ "The receiver cannot be a forwader"
+ "numArgs >= (NumSendTrampolines - 1) ifTrue:
+ [self MoveCq: newMethodArgCount R: SendNumArgsReg]."
+ "Load inline cache with method index"
+ "self MoveUniqueC32: litIndex R: ClassReg.
+ (self Call: (sendTable at: (newMethodArgCount min: NumSendTrampolines - 1))) annotation: annotation.
+ self voidReceiverOptStatus.
+ self ssPushRegister: ReceiverResultReg."
+ ^ EncounteredUnknownBytecode "Need to finish implementation"!

Item was added:
+ ----- Method: SistaCogitClone>>genDivInlinePrimitive: (in category 'inline primitive binary generators') -----
+ genDivInlinePrimitive: primIndex
+ "2003 /
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant) "
+ "2004 //
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant) "
+ "2005 \\
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant) "
+ "2006 quo:
+ Smi, Smi => Smi (no overflow, optimised if one operand is a constant) "
+
+ "We don't deal with constants here. Too complex and does nto bring much"
+ | ra rr jumpExact jumpSameSign |
+ <var: #jumpExact type: #'AbstractInstruction *'>
+ <var: #jumpSameSign type: #'AbstractInstruction *'>
+ self allocateRegForStackTopTwoEntriesInto: [:rTop :rNext | ra := rTop. rr := rNext ].
+ self ssTop popToReg: ra.
+ self ssPop: 1.
+ self ssTop popToReg: rr.
+ self ssPop: 1.
+ self assert: backEnd canDivQuoRem.
+ "arg non zero, no overflow check. / remains (unused in optimised code)"
+ primIndex caseOf: {
+ [4] -> [objectRepresentation genShiftAwaySmallIntegerTagsInScratchReg: ra.
+ objectRepresentation genShiftAwaySmallIntegerTagsInScratchReg: rr.
+ self DivR: ra R: rr Quo: rr Rem: TempReg.
+ "If remainder is zero, success"
+ self CmpCq: 0 R: TempReg.
+ jumpExact := self JumpZero: 0.
+ "If arg and remainder signs are different we must round down."
+ objectRepresentation genConvertIntegerToSmallIntegerInReg: ra.
+ self XorR: TempReg R: ra.
+ (self lastOpcode setsConditionCodesFor: JumpZero) ifFalse:
+ [self CmpCq: 0 R: ra].
+ jumpSameSign := self JumpGreaterOrEqual: 0.
+ self SubCq: 1 R: rr.
+ jumpSameSign jmpTarget: (jumpExact jmpTarget: self Label).
+ objectRepresentation genConvertIntegerToSmallIntegerInReg: rr ].
+ [5] -> [objectRepresentation genRemoveSmallIntegerTagsInScratchReg: ra.
+ objectRepresentation genRemoveSmallIntegerTagsInScratchReg: rr.
+ self DivR: ra R: rr Quo: TempReg Rem: rr.
+ "If remainder is zero we're done."
+ self CmpCq: 0 R: rr.
+ jumpExact := self JumpZero: 0.
+ "If arg and remainder signs are different we must reflect around zero."
+ self XorR: rr R: ra.
+ (self lastOpcode setsConditionCodesFor: JumpZero) ifFalse:
+ [self CmpCq: 0 R: ra].
+ jumpSameSign := self JumpGreaterOrEqual: 0.
+ self XorR: rr R: ra.
+ self AddR: ra R: rr.
+ jumpSameSign jmpTarget: (jumpExact jmpTarget: self Label).
+ objectRepresentation genSetSmallIntegerTagsIn: rr ].
+ [6] -> [objectRepresentation genShiftAwaySmallIntegerTagsInScratchReg: ra.
+ objectRepresentation genShiftAwaySmallIntegerTagsInScratchReg: rr.
+ self DivR: ra R: rr Quo: rr Rem: ra.
+ objectRepresentation genConvertIntegerToSmallIntegerInReg: rr].
+ } otherwise: [^EncounteredUnknownBytecode].
+ self ssPushRegister: rr.
+ ^0!

Item was added:
+ ----- Method: SistaCogitClone>>genEnsureEnoughSlots (in category 'mapped inline primitive generators') -----
+ genEnsureEnoughSlots
+ "50 EnsureEnoughWords
+ literal which is a Smi => ret value is receiver"
+ |slots skip|
+ <var: #skip type: #'AbstractInstruction *'>
+ self assert: (self ssTop type = SSConstant and: [objectMemory isIntegerObject: self ssTop constant]).
+ slots := objectMemory integerValueOf: self ssTop constant.
+ self ssFlushTo: simStackPtr - 1.
+ self
+ MoveAw: objectMemory freeStartAddress R: TempReg;
+ CmpCq: objectMemory getScavengeThreshold - (objectMemory bytesPerOop * slots) R: TempReg.
+ skip := self JumpBelow: 0.
+ objectRepresentation genSetGCNeeded.
+ self CallRT: ceCheckForInterruptTrampoline.
+ skip jmpTarget: self Label.
+ self annotateBytecode: skip getJmpTarget.
+ ^0!

Item was added:
+ ----- Method: SistaCogitClone>>genJumpBinaryInlinePrimitive: (in category 'inline primitive generators') -----
+ genJumpBinaryInlinePrimitive: primIndex
+ | target testReg |
+ self assert: self ssTop type = SSConstant.
+ target := self eventualTargetOf: ((objectMemory integerValueOf: self ssTop constant) + 3 + bytecodePC).
+ testReg := self allocateRegForStackEntryAt: 1.
+ (self ssValue: 1) popToReg: testReg.
+ self ssPop: 2.
+ primIndex caseOf: {
+ "7016 jumpIfWritable:
+ Not a forwarder, literal which is a Smi"
+ [16] -> [self cppIf: #IMMUTABILITY
+ ifTrue: [(objectRepresentation genJumpMutable: testReg scratchReg: TempReg) jmpTarget: (self ensureFixupAt: target).]
+ ifFalse: [self Jump: (self ensureFixupAt: target)].
+ ^0].
+ "7017 jumpIfReadOnly:
+ Not a forwarder, literal which is a Smi"
+ [17] -> [self cppIf: #IMMUTABILITY
+ ifTrue: [(objectRepresentation genJumpImmutable: testReg scratchReg: TempReg) jmpTarget: (self ensureFixupAt: target)]
+ ifFalse: [0"Do nothing - fall through"].
+ ^0].
+ "7018 jumpIfYoung:
+ Not a forwarder, literal which is a Smi"
+ [18] -> [self CmpCw: objectMemory storeCheckBoundary R: testReg.
+ self JumpBelow: (self ensureFixupAt: target).
+ ^0].
+ "7019 jumpIfOld:
+ Not a forwarder, literal which is a Smi"
+ [19] -> [self CmpCw: objectMemory storeCheckBoundary R: testReg.
+ self JumpAboveOrEqual: (self ensureFixupAt: target).
+ ^0].
+ }.
+ ^ EncounteredUnknownBytecode
+ !

Item was added:
+ ----- Method: SistaCogitClone>>genJumpTrinaryInlinePrimitive: (in category 'inline primitive generators') -----
+ genJumpTrinaryInlinePrimitive: primIndex
+ "Note: those tests work with forwarders (wrong class index)"
+ | testReg target behavior targetFixUp |
+ <var: #targetFixUp type: #'BytecodeFixup *'>
+ self assert: self ssTop type = SSConstant.
+ self assert: (self ssValue: 1) type = SSConstant.
+ testReg := self allocateRegForStackEntryAt: 2.
+ (self ssValue: 2) popToReg: testReg.
+ behavior := (self ssValue: 1) constant.
+ target := self eventualTargetOf: ((objectMemory integerValueOf: self ssTop constant) + 3 + bytecodePC).
+ self ssPop: 3.
+ targetFixUp := self cCoerceSimple: (self ensureFixupAt: target) to: #'AbstractInstruction *'.
+ primIndex caseOf: {
+ [0] -> ["8000 jumpIfInstanceOf:distance:
+ Anything, literal which is a Behavior, literal which is a Smi"
+ objectRepresentation branchIf: testReg instanceOfBehavior: behavior target: targetFixUp.
+ ^0].
+ [1] -> ["8001 jumpIfNotInstanceOf:distance:
+ Anything, literal which is a Behavior, literal which is a Smi"
+ objectRepresentation branchIf: testReg notInstanceOfBehavior: behavior target: targetFixUp.
+ ^0].
+ [2] -> ["8002 jumpIfInstanceOfOneOf:distance:
+ Anything, Array of behaviors, literal which is a Smi"
+ objectRepresentation branchIf: testReg instanceOfBehaviors: behavior target: targetFixUp.
+ ^0].
+ [3] -> ["8003 jumpIfNotInstanceOfOneOf:distance:
+  Anything, Array of behaviors, literal which is a Smi"
+ objectRepresentation branchIf: testReg notInstanceOfBehaviors: behavior target: targetFixUp.
+ ^0].
+ }.
+ ^ EncounteredUnknownBytecode
+
+ !

Item was added:
+ ----- Method: SistaCogitClone>>genJumpUnaryInlinePrimitive: (in category 'inline primitive generators') -----
+ genJumpUnaryInlinePrimitive: primIndex
+ "6000 backjumpNoInterrupt
+ literal which is a Smi"
+ primIndex = 0 ifTrue:
+ [|targetBytecodePC|
+ self assert: self ssTop type = SSConstant.
+ targetBytecodePC := (objectMemory integerValueOf: self ssTop constant) + 3 + bytecodePC.
+ self ssPop: 1.
+ self ssFlushTo: simStackPtr.
+ deadCode := true. "can't fall through"
+ self Jump: (self fixupAt: targetBytecodePC).
+ ^0].
+ ^EncounteredUnknownBytecode!

Item was added:
+ ----- Method: SistaCogitClone>>genMappedInlinePrimitive: (in category 'mapped inline primitive generators') -----
+ genMappedInlinePrimitive: primIndex
+ "SistaV1: 236 11101100 iiiiiiii callMappedInlinedPrimitive"
+ "Number of arguments:
+ 0-49 nullary
+ 50-99 unary
+ 100-149  binary
+ 150-199 trinary
+ 200-255 variable"
+ "Specification:
+ 50 EnsureEnoughWords
+ literal which is a Smi => ret value is receiver
+ 150 immCheckPointerAt:put:
+ pointer object (Fixed sized or not) and not a context, Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 151 immCheckStoreCheckPointerAt:put:
+ pointer object (Fixed sized or not) and not a context, Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 152 immCheckMaybeContextPointerAt:put:
+ pointer object (Fixed sized or not), Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 153 immCheckMaybeContextStoreCheckPointerAt:put:
+ pointer object (Fixed sized or not), Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 154 immCheckByteAt:put:
+ byte object, Smi, 8 bits unsigned Smi => arg2 (1-based, optimised if arg1 is a constant)
+ 155 immCheckShortAt:put:
+ short object, Smi, 16 bits unsigned Smi => arg2 (1-based, optimised if arg1 is a constant)
+ 156 immCheckWordAt:put:
+ word object, Smi, 32 bits unsigned Smi => arg2 (1-based, optimised if arg1 is a constant)
+ 157 immCheckDoubleWordAt:put:
+ double word object, Smi, 64 bits unsigned Smi or LargePositiveInteger => arg2 (1-based, optimised if arg1 is a constant)
+ 250 directCall
+ method to call on top of stack =>  (variable number of parameters)"
+ primIndex caseOf:
+ {
+ [50] -> [^self genEnsureEnoughSlots].
+ [150] -> [^self genPointerAtPutMaybeContext: false storeCheck: false immutabilityCheck: true].
+ [151] -> [^self genPointerAtPutMaybeContext: false storeCheck: true immutabilityCheck: true].
+ [152] -> [^self genPointerAtPutMaybeContext: true storeCheck: false immutabilityCheck: true].
+ [153] -> [^self genPointerAtPutMaybeContext: true storeCheck: true immutabilityCheck: true].
+ [154] -> [self cppIf: #IMMUTABILITY
+ ifTrue: [^self genByteAtPutImmutabilityCheck]
+ ifFalse: [self genByteAtPut.
+ self annotateBytecode: self Label.
+ ^0]].
+ [155] -> [^EncounteredUnknownBytecode "not implemented, missing short instruction in Cog RTL"].
+ [156] -> [^EncounteredUnknownBytecode "not implemented, need to deal with LargePositiveInteger in 32 bits"].
+ [157] -> [^EncounteredUnknownBytecode "not implemented, need to deal with LargePositiveInteger in 64 bits"].
+ [250] -> [^self genDirectCall].
+ } otherwise: [^EncounteredUnknownBytecode].
+ !

Item was added:
+ ----- Method: SistaCogitClone>>genMoveAndAdjustSSEntry:into: (in category 'inline primitive generators') -----
+ genMoveAndAdjustSSEntry: ssEntry into: reg
+ <var: #ssEntry type: #'SimStackEntry *'>
+ <inline: true>
+ | adjust |
+ adjust := (objectMemory baseHeaderSize >> objectMemory shiftForWord) - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
+ ssEntry type = SSConstant
+ ifTrue: [self MoveCq: (objectMemory integerValueOf: ssEntry constant) + adjust R: reg.
+      ssEntry spilled ifTrue: [self AddCq: objectMemory wordSize R: SPReg]]
+ ifFalse:
+ [ssEntry popToReg: reg.
+ objectRepresentation genConvertSmallIntegerToIntegerInReg: reg.
+ adjust ~= 0 ifTrue: [ self AddCq: adjust R: reg. ]]. !

Item was changed:
  ----- Method: SistaCogitClone>>genNullaryInlinePrimitive: (in category 'inline primitive generators') -----
  genNullaryInlinePrimitive: prim
- "Nullary 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>>#nullaryInlinePrimitive:"
-
  <option: #SistaVM>
  ^EncounteredUnknownBytecode!

Item was added:
+ ----- Method: SistaCogitClone>>genPointerAtPutConstantMaybeContext:storeCheck:immutabilityCheck: (in category 'inline primitive generators') -----
+ genPointerAtPutConstantMaybeContext: maybeContext storeCheck: needsStoreCheck immutabilityCheck: needsImmCheck
+ | rcvrReg valReg indexCst |
+ indexCst := (objectMemory integerValueOf: (self ssValue: 1) constant) - 1.
+ "we want to have on top of stack the value to write descriptor."
+ (maybeContext or: [needsImmCheck])
+ ifTrue: [ valReg := ClassReg.
+ self voidReceiverResultRegContainsSelf.
+ rcvrReg := ReceiverResultReg ]
+ ifFalse: [ valReg := self allocateRegForStackEntryAt: 0 notConflictingWith: 0.
+  needsStoreCheck
+ ifFalse: [rcvrReg := self allocateRegForStackEntryAt: 2 notConflictingWith: (self registerMaskFor: valReg)]
+ ifTrue: [self voidReceiverResultRegContainsSelf.
+ rcvrReg := ReceiverResultReg]].
+ "If rcvr is valReg, we flush it. Could generate a move instead but not that common"
+ self ssAllocateRequiredReg: valReg upThrough: simStackPtr - 2.
+ self ssAllocateRequiredReg: rcvrReg upThrough: simStackPtr - 3.
+ self ssTop popToReg: valReg.
+ self ssPop: 1.
+ self ssTop spilled ifTrue: [self AddCq: objectRepresentation wordSize R: SPReg].
+ self ssPop: 1.
+ self ssTop popToReg: rcvrReg.
+ self ssPop: 1.
+ self ssPushRegister: valReg.
+
+ maybeContext
+ ifFalse:
+ [^self
+ genGenericStorePop: false
+ slotIndex: indexCst
+ destReg: rcvrReg
+ needsStoreCheck: needsStoreCheck
+ needsRestoreRcvr: false
+ needsImmutabilityCheck: needsImmCheck]
+ ifTrue:
+ [^self
+ genGenericStorePop: false
+ MaybeContextSlotIndex: indexCst
+ needsStoreCheck: needsStoreCheck
+ needsRestoreRcvr: false
+ needsImmutabilityCheck: needsImmCheck]!

Item was added:
+ ----- Method: SistaCogitClone>>genPointerAtPutImmCheckAndStoreCheck (in category 'mapped inline primitive generators') -----
+ genPointerAtPutImmCheckAndStoreCheck
+ | ra1 ra2 rr adjust scratchReg immutableJump jmpImmediate jmpDestYoung jmpSourceOld jumpRemembered indexIsCst |
+ <var: #jmpSourceOld type: #'AbstractInstruction *'>
+ <var: #jmpDestYoung type: #'AbstractInstruction *'>
+ <var: #jmpImmediate type: #'AbstractInstruction *'>
+ <var: #immutableJump type: #'AbstractInstruction *'>
+ <var: #jumpRemembered type: #'AbstractInstruction *'>
+ "Assumes rr is not a context and no store check is needed"
+ indexIsCst := (self ssValue: 1) type = SSConstant.
+ self ssFlushTo: simStackPtr - 3.
+ rr := ReceiverResultReg.
+ ra1 := TempReg.
+ ra2 := ClassReg.
+ scratchReg := Arg0Reg.
+ adjust := (objectMemory baseHeaderSize >> objectMemory shiftForWord) - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
+ (self ssValue: 2) popToReg: rr.
+ indexIsCst
+ ifFalse:
+ [(self ssValue: 1) popToReg: ra1.
+ objectRepresentation genConvertSmallIntegerToIntegerInReg: ra1.
+ adjust ~= 0 ifTrue: [self AddCq: adjust R: ra1]]
+ ifTrue: [self MoveCq: (objectMemory integerValueOf: (self ssValue: 1) constant) + adjust R: ra1].
+ self ssTop popToReg: ra2.
+ self ssPop: 3.
+ self ssPushRegister: ra2.
+ self voidReceiverResultRegContainsSelf.
+
+ immutableJump := self genJumpImmutable: rr scratchReg: scratchReg.
+ self MoveR: ra2 Xwr: ra1 R: rr.
+
+ "store check"
+ jmpImmediate := self genJumpImmediate: ra2.
+ "Get the old/new boundary in scratchReg"
+ self MoveCw: objectMemory storeCheckBoundary R: scratchReg.
+ "Is target young?  If so we're done"
+ self CmpR: scratchReg R: rr. "N.B. FLAGS := destReg - scratchReg"
+ jmpDestYoung := self JumpBelow: 0.
+ "Is value stored old?  If so we're done."
+ self CmpR: scratchReg R: ra2. "N.B. FLAGS := valueReg - scratchReg"
+ jmpSourceOld := self JumpAboveOrEqual: 0.
+ "value is young and target is old.
+ Need to remember this only if the remembered bit is not already set."
+ jumpRemembered := objectRepresentation genIfRequiredCheckRememberedBitOf: rr scratch: scratchReg.
+ "Set the inst var index for the benefit of the immutability check. The trampoline will
+ repeat the check to choose between the immutbality violation and the store check."
+ immutableJump jmpTarget: self Label.
+ self PushR: ra2.
+ self SubCq: 1 + adjust R: ra1. "index 0-relative for trampoline, ra1 unused afterwards"
+ objectRepresentation genVarIndexCallStoreTrampoline.
+ self PopR: ra2.
+ jmpImmediate jmpTarget:
+ (jmpDestYoung jmpTarget:
+ (jmpSourceOld jmpTarget:
+ self Label)).
+ self setIfRequiredTargetOf: jumpRemembered toTargetOf: jmpImmediate.
+
+ ^0!

Item was added:
+ ----- Method: SistaCogitClone>>genPointerAtPutImmCheckButNoStoreCheck (in category 'mapped inline primitive generators') -----
+ genPointerAtPutImmCheckButNoStoreCheck
+ | ra1 ra2 rr adjust mutableJump immutabilityFailure indexIsCst |
+ <var: #mutableJump type: #'AbstractInstruction *'>
+ <var: #immutabilityFailure type: #'AbstractInstruction *'>
+ "Assumes rr is not a context and no store check is needed"
+ indexIsCst := (self ssValue: 1) type = SSConstant.
+ self ssFlushTo: simStackPtr - 3.
+ rr := ReceiverResultReg.
+ ra1 := TempReg.
+ ra2 := ClassReg.
+ (self ssValue: 2) popToReg: rr.
+ adjust := (objectMemory baseHeaderSize >> objectMemory shiftForWord) - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
+ indexIsCst
+ ifFalse:
+ [(self ssValue: 1) popToReg: ra1.
+ objectRepresentation genConvertSmallIntegerToIntegerInReg: ra1.
+ adjust ~= 0 ifTrue: [self AddCq: adjust R: ra1]]
+ ifTrue: [self MoveCq: (objectMemory integerValueOf: (self ssValue: 1) constant) + adjust R: ra1].
+ self ssTop popToReg: ra2.
+ self ssPop: 3.
+ self ssPushRegister: ra2.
+ self voidReceiverResultRegContainsSelf.
+
+ mutableJump := self genJumpMutable: rr scratchReg: Arg0Reg.
+ "simStack is flushed, but result is not"
+ self PushR: ra2.
+ self SubCq: 1 + adjust R: ra1. "index 0-relative for trampoline, ra1 unused afterwards"
+ objectRepresentation genVarIndexCallStoreTrampoline.
+ self PopR: ra2.
+ immutabilityFailure := self Jump: 0.
+
+ mutableJump jmpTarget: self Label.
+ self MoveR: ra2 Xwr: ra1 R: rr.
+ immutabilityFailure jmpTarget: self Label.
+ ^0!

Item was added:
+ ----- Method: SistaCogitClone>>genPointerAtPutMaybeContext:storeCheck:immutabilityCheck: (in category 'mapped inline primitive generators') -----
+ genPointerAtPutMaybeContext: maybeContext storeCheck: needsStoreCheck immutabilityCheck: needsImmCheck
+ "150 immCheckPointerAt:put:
+ pointer object (Fixed sized or not) and not a context, Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 151 immCheckStoreCheckPointerAt:put:
+ pointer object (Fixed sized or not) and not a context, Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 152 immCheckMaybeContextPointerAt:put:
+ pointer object (Fixed sized or not), Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 153 immCheckMaybeContextStoreCheckPointerAt:put:
+ pointer object (Fixed sized or not), Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)"
+ | index |
+ index := self ssValue: 1.
+ "Instruction always annoted - uncommon, IMMUTABILITY disabled. We need a Nop since previous instr can be annotated."
+ self cppIf: #IMMUTABILITY ifTrue: [] ifFalse: [ needsImmCheck ifTrue: [ self annotateBytecode: self Nop ] ].
+ "Optimised case if arg1 is constant"
+ index type = SSConstant
+ ifTrue:  [^self genPointerAtPutConstantMaybeContext: maybeContext storeCheck: needsStoreCheck immutabilityCheck: needsImmCheck].
+ maybeContext ifTrue: [^EncounteredUnknownBytecode "not implemented, not used right now, for tempAt: optimisation on non constant"].
+ self cppIf: #IMMUTABILITY ifTrue:
+ [needsImmCheck
+ ifTrue: [needsStoreCheck
+ ifTrue: [^self genPointerAtPutImmCheckAndStoreCheck]
+ ifFalse: [^self genPointerAtPutImmCheckButNoStoreCheck] ] ].
+ ^self genPointerAtPutStoreCheck: needsStoreCheck!

Item was added:
+ ----- Method: SistaCogitClone>>genPointerAtPutStoreCheck: (in category 'mapped inline primitive generators') -----
+ genPointerAtPutStoreCheck: needsStoreCheck
+ | ra1 ra2 rr adjust |
+ "Assumes rr is not a context and no immutability check is needed"
+ "The store check requires rr to be ReceiverResultReg"
+ self
+ allocateRegForStackTopThreeEntriesInto: [:rTop :rNext :rThird | ra2 := rTop. ra1 := rNext. rr := rThird ]
+ thirdIsReceiver: needsStoreCheck.
+ 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.
+ 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.
+ needsStoreCheck ifTrue:
+ [ self assert: needsFrame.
+ objectRepresentation genStoreCheckReceiverReg: rr valueReg: ra2 scratchReg: TempReg inFrame: true].
+ self ssPushRegister: ra2.
+ ^0!

Item was changed:
  ----- Method: SistaCogitClone>>genQuaternaryInlinePrimitive: (in category 'inline primitive generators') -----
  genQuaternaryInlinePrimitive: prim
+ ^ EncounteredUnknownBytecode!
- "Quaternary 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>>#quaternaryInlinePrimitive:"
- | needStoreCheck sourceReg stopReg objReg adjust jmp cmp isStartCst isStopCst startCst stopCst iteratorReg |
- <var: #jmp type: #'AbstractInstruction *'>
- <var: #cmp type: #'AbstractInstruction *'>
- prim = 0 ifFalse: [^EncounteredUnknownBytecode].
-
- "4000 Pointer Object>> fillFrom:to:with: The receiver is a Pointer object. the middle two arguments are smallintegers. Last argument is any object. Fills the object in between the two indexes with last argument. Receiver is guaranteed to be mutable. The pointer accesses are raw (no inst var check). If ExtB is set to 1, no store check is present. Else a single store check is done for the bulk operation. Answers the receiver."
- needStoreCheck := self sistaNeedsStoreCheck.
- extB := numExtB := 0.
-
- "Allocate reg for src, objToStore, iterator and stop."
- sourceReg := needStoreCheck
- ifTrue: [ self ssAllocateRequiredReg: ReceiverResultReg.
- self voidReceiverResultRegContainsSelf.
- ReceiverResultReg ]
- ifFalse: [ self allocateRegForStackEntryAt: 3 notConflictingWith: self emptyRegisterMask ].
- (self ssValue: 3) popToReg: sourceReg.
- objReg := self allocateRegForStackEntryAt: 0 notConflictingWith: (self registerMaskFor: sourceReg).
- self ssTop popToReg: objReg.
-
- "Set up iterator to first index to write and stop to last index to write"
- adjust := (objectMemory baseHeaderSize >> objectMemory shiftForWord) - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
- isStartCst := (self ssValue: 2) type = SSConstant.
- isStopCst := (self ssValue: 1) type = SSConstant.
- isStartCst ifTrue: [startCst := adjust + (objectMemory integerValueOf: (self ssValue: 2) constant)].
- isStopCst ifTrue: [stopCst := adjust + (objectMemory integerValueOf: (self ssValue: 1) constant)].
-
- (isStartCst
- and: [isStopCst
- and: [stopCst - startCst < 7 ]]) "The other path generates at least 7 instructions"
- ifTrue: ["unroll"
- startCst
- to: stopCst
- do: [ :i | self MoveMw: i r: sourceReg R: objReg ] ]
- ifFalse: ["loop"
- stopReg := self allocateRegNotConflictingWith: (self registerMaskFor: sourceReg and: objReg).
- iteratorReg := self allocateRegNotConflictingWith: (self registerMaskFor: sourceReg and: objReg and: stopReg).
- isStartCst
- ifTrue: [ self MoveCq: startCst R: iteratorReg ]
- ifFalse: [ (self ssValue: 2) popToReg: iteratorReg.
- adjust ~= 0 ifTrue: [ self AddCq: adjust R: iteratorReg ] ].
- isStopCst
- ifTrue: [ self MoveCq: stopCst R: stopReg ]
- ifFalse: [ (self ssValue: 1) popToReg: stopReg.
- adjust ~= 0 ifTrue: [ self AddCq: adjust R: stopReg ] ].
- cmp := self CmpR: stopReg R: iteratorReg.
- jmp := self JumpAbove: 0.
- self MoveR: objReg Xwr: iteratorReg R: sourceReg.
- self AddCq: 1 R: iteratorReg.
- self Jump: cmp.
- jmp jmpTarget: self Label].
-
- needStoreCheck ifTrue: [objectRepresentation genStoreCheckReceiverReg: sourceReg valueReg: objReg scratchReg: TempReg inFrame: true].
-
- self ssPop: 4.
- self ssPushRegister: sourceReg.
- ^0!

Item was changed:
  ----- Method: SistaCogitClone>>genQuinaryInlinePrimitive: (in category 'inline primitive generators') -----
  genQuinaryInlinePrimitive: prim
+ ^ EncounteredUnknownBytecode!
- "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>>#quaternaryInlinePrimitive:"
- ^EncounteredUnknownBytecode!

Item was added:
+ ----- Method: SistaCogitClone>>genSistaInlinePrimitive: (in category 'inline primitive generators') -----
+ genSistaInlinePrimitive: prim
+ "SistaV1: 248 11111000 iiiiiiii mjjjjjjj Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution. This is the dispatch for unmapped sista inlined primitives."
+
+ prim < 1000 ifTrue:
+ [^self genNullaryInlinePrimitive: prim].
+
+ prim < 2000 ifTrue:
+ [^self genUnaryInlinePrimitive: prim - 1000].
+
+ prim < 3000 ifTrue:
+ [^self genBinaryInlinePrimitive: prim - 2000].
+
+ prim < 4000 ifTrue:
+ [^self genTrinaryInlinePrimitive: prim - 3000].
+
+ prim < 5000 ifTrue:
+ [^self genQuaternaryInlinePrimitive: prim - 4000].
+
+ prim < 6000 ifTrue:
+ [^self genQuinaryInlinePrimitive: prim - 5000].
+
+ prim < 7000 ifTrue:
+ [^self genJumpUnaryInlinePrimitive: prim - 6000].
+
+   prim < 8000 ifTrue:
+ [^self genJumpBinaryInlinePrimitive: prim - 7000].
+
+ ^ self genJumpTrinaryInlinePrimitive: prim - 8000.!

Item was changed:
  ----- Method: SistaCogitClone>>genTrinaryInlinePrimitive: (in category 'inline primitive generators') -----
  genTrinaryInlinePrimitive: prim
+ "Bulk comment, each sub method has its own comment
+ 3000 pointerAt:put:
+ Mutable pointer object (Fixed sized or not) and not a context, Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 3001 storeCheckPointerAt:put:
+ Mutable pointer object (Fixed sized or not) and not a context, Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 3002 maybeContextPointerAt:put:
+ Mutable pointer object (Fixed sized or not), Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 3003 maybeContextStoreCheckPointerAt:put:
+ Mutable pointer object (Fixed sized or not), Smi, Anything => arg2 (1-based, optimised if arg1 is a constant)
+ 3004 byteAt:put:
+ Mutable byte object, Smi, 8 bits unsigned Smi => arg2 (1-based, optimised if arg1 is a constant)
+ 3005 shortAt:put:
+ Mutable short object, Smi, 16 bits unsigned Smi => arg2 (1-based, optimised if arg1 is a constant)
+ 3006 wordAt:put:
+ Mutable word object, Smi, 32 bits unsigned Smi => arg2 (1-based, optimised if arg1 is a constant)
+ 3007 doubleWordAt:put:
+ Mutable double word object, Smi, 64 bits unsigned Smi or LargePositiveInteger => arg2 (1-based, optimised if arg1 is a constant)
+ 3021 is deprecated."
+ prim <= 7 ifTrue: [^self genAtPutInlinePrimitive: prim].
+ prim = 21 ifTrue: [^self genByteEqualsInlinePrimitive: prim].
- "trinary 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:"
-
- prim < 10 ifTrue: [^ self genAtPutInlinePrimitive: prim].
- prim = 21 ifTrue: [^ self genByteEqualsInlinePrimitive: prim].
  ^ EncounteredUnknownBytecode!

Item was added:
+ ----- Method: SistaCogitClone>>genUnaryClassPrimitive (in category 'inline primitive unary generators') -----
+ genUnaryClassPrimitive
+ "1000 rawClass
+ not a forwarder => Behavior (Same as class special send, but receiver is not a forwarder)"
+
+ "Important performance note:
+ In Scorch, typically a value is known as not being a forwarder if there is a trap.
+ If the trap is due to a monomorphic send, the #class send leads to:
+ trapIf: X notInstanceOf: C
+ X rawClass
+ therefore X rawClass is simplified in Scorch to the cst:C
+ The rawClass is therefore used only for PICs.
+ trapIf: X notInstanceOf: C, C', C''
+ X rawClass
+ This unsafe operation is important to avoid register flush, but the performance
+ difference in differencing rawClass for immediate and rawClass for non immediate
+ classes is not that relevant"
+
+ | topReg jumpIsImm destReg |
+ <var: #jumpIsImm type: #'AbstractInstruction *'>
+ topReg := self allocateRegForStackEntryAt: 0 notConflictingWith: 0.
+ destReg := self allocateRegNotConflictingWith: (self registerMaskFor: topReg).
+ self ssTop popToReg: topReg.
+
+ "1. Read the class index"
+ self MoveR: topReg R: TempReg.
+ self AndCq: objectMemory tagMask R: TempReg.
+ jumpIsImm := self JumpNonZero: 0.
+ self flag: #endianness.
+ "Get least significant half of header word in destReg"
+ self MoveMw: 0 r: topReg R: TempReg.
+ "mask off class index"
+ self AndCq: objectMemory classIndexMask R: TempReg.
+
+ "2. Read the class from class index"
+ jumpIsImm jmpTarget: self Label.
+ objectRepresentation genGetClassObjectOfClassIndex: TempReg into: destReg scratchReg: topReg.
+ self ssPop: 1.
+ ^self ssPushRegister: destReg!

Item was added:
+ ----- Method: SistaCogitClone>>genUnaryConvertInlinePrimitive: (in category 'inline primitive unary generators') -----
+ genUnaryConvertInlinePrimitive: primIndex
+ | resultReg |
+ self assert: (primIndex between: 30 and: 32).
+ primIndex caseOf: {
+ "1030 characterAsInteger
+ Character => 22 bits strictly positive Smi (Unicode)"
+ [30] -> [resultReg := self allocateRegForStackEntryAt: 0.
+ self ssTop popToReg: resultReg.
+ objectRepresentation genConvertCharacterToSmallIntegerInReg: resultReg].
+ "1031 smallFloatAsInteger
+ SmallFloat => Smi"
+ [31] -> [^EncounteredUnknownBytecode "to implement"].
+ "1032 smiAsFloat
+ Smi => SmallFloat"
+ [32] -> [resultReg := self allocateRegForStackEntryAt: 0.
+ self ssTop popToReg: resultReg.
+ self assert: self processorHasDoublePrecisionFloatingPointSupport.
+ self MoveR: resultReg R: TempReg.
+ self genConvertSmallIntegerToIntegerInReg: TempReg.
+ self ConvertR: TempReg Rd: DPFPReg0.
+ self flag: #TODO. "Should never fail"
+ self
+ genAllocFloatValue: DPFPReg0
+ into: resultReg
+ scratchReg: TempReg
+ scratchReg: NoReg. "scratch2 for V3 only"]
+ }.
+ self ssPop: 1.
+ ^self ssPushRegister: resultReg!

Item was added:
+ ----- Method: SistaCogitClone>>genUnaryHashInlinePrimitive: (in category 'inline primitive unary generators') -----
+ genUnaryHashInlinePrimitive: primIndex
+ | rcvrReg resultReg |
+ self assert: (primIndex between: 20 and: 23).
+ primIndex caseOf: {
+ "1020 objectIdentityHash
+ non-immediate and non-behavior => 22 bits strictly positive Smi"
+ [20] -> [rcvrReg := self allocateRegForStackEntryAt: 0.
+ resultReg := self allocateRegNotConflictingWith: (self registerMaskFor: rcvrReg).
+ self ssTop popToReg: rcvrReg.
+ objectRepresentation genGetIdentityHash: rcvrReg resultReg: resultReg].
+ "1021 smiIdentityHash
+ Smi => Smi"
+ [21] -> [resultReg := self allocateRegForStackEntryAt: 0.
+ self ssTop popToReg: resultReg].
+ "1022 charIdentityHash
+ Character => 22 bits strictly positive Smi"
+ [22] -> [resultReg := self allocateRegForStackEntryAt: 0.
+ self ssTop popToReg: resultReg.
+ objectRepresentation genConvertCharacterToSmallIntegerInReg: resultReg].
+ "1023 smallfloatIdentityHash
+ SmallFloat => Smi"
+ [23] -> [resultReg := self allocateRegForStackEntryAt: 0.
+ objectRepresentation genConvertSmallFloatToSmallFloatHashAsIntegerInReg: resultReg scratch: TempReg].
+ "1024 behaviorIdentityHash
+ Behavior => 22 bits strictly positive Smi"
+ [24] -> [^EncounteredUnknownBytecode "not implemented"].
+ }.
+ self ssPop: 1.
+ ^self ssPushRegister: resultReg!

Item was changed:
+ ----- Method: SistaCogitClone>>genUnaryInlinePrimitive: (in category 'inline primitive unary generators') -----
+ genUnaryInlinePrimitive: primIndex
+ "Bulk comments: each sub-method has its own comment with the specific case.
+ 1000 rawClass
+ not a forwarder => Behavior (Same as class special send, but receiver is not a forwarder)
+ 1001 numSlots
+ pointer object => Smi between 0 and SmallInteger maxVal // 4 - 1 (Answers total size in pointer-sized slots)
+ 1002 numBytes
+ byte object => Smi between 0 and SmallInteger maxVal - 9 (Includes compiled code)
+ 1003 numShorts
+ short object => Smi between 0 and SmallInteger maxVal - 9
+ 1004 numWords
+ word object => Smi between 0 and SmallInteger maxVal - 9
+ 1005 numDoubleWords
+ double word object => Smi between 0 and SmallInteger maxVal - 9
+ 1011 RawNew
+ literal which is a fixed-sized behavior => instance of the receiver with fields nilled out
+ 1012 RawNewNoInit
+ literal which is a fixed-sized behavior => instance of the receiver (Fields of returned value contain undefined data)
+ 1020 objectIdentityHash
+ non-immediate and non-behavior => 22 bits strictly positive Smi
+ 1021 smiIdentityHash
+ Smi => Smi
+ 1022 charIdentityHash
+ Character => 22 bits strictly positive Smi
+ 1023 smallfloatIdentityHash
+ SmallFloat => Smi
+ 1024 behaviorIdentityHash
+ Behavior => 22 bits strictly positive Smi
+ 1030 characterAsInteger
+ Character => 22 bits strictly positive Smi (Unicode)
+ 1031 smallFloatAsInteger
+ SmallFloat => Smi
+ 1032 smiAsFloat
+ Smi => SmallFloat
+ 1040 unforward
+ Anything => Not a forwarder
+ 1041 possibleRoot
+ non-immediate, not a forwarder => receiver is returned (should be effect-only) (If old, becomes gray and remembered to allow many unchecked stores in a row afterwards)"
+ primIndex = 0 ifTrue: [^self genUnaryClassPrimitive].
+ primIndex <= 6 ifTrue: [^self genUnarySizeInlinePrimitive: primIndex].
+ primIndex < 11 ifTrue: [^EncounteredUnknownBytecode].
+ primIndex <= 12 ifTrue: [^self genUnaryNewInlinePrimitive: primIndex].
+ primIndex < 20 ifTrue: [^EncounteredUnknownBytecode].
+ primIndex <= 24 ifTrue: [^self genUnaryHashInlinePrimitive: primIndex].
+ primIndex < 30 ifTrue: [^EncounteredUnknownBytecode].
+ primIndex <= 32 ifTrue: [^self genUnaryConvertInlinePrimitive: primIndex].
+ primIndex = 39 ifTrue: [^self genUnaryUnforwardNonImmediateInlinePrimitive].
+ primIndex = 40 ifTrue: [^self genUnaryUnforwardInlinePrimitive].
+ primIndex = 41 ifTrue: [^self genUnaryPossibleRootInlinePrimitive].
+ ^EncounteredUnknownBytecode!
- ----- Method: SistaCogitClone>>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 allocateRegForStackEntryAt: 0.
- resultReg := self allocateRegNotConflictingWith: (self registerMaskFor: rcvrReg).
- prim
- caseOf: {
- "00 unchecked class"
- [1] -> "01 unchecked pointer numSlots"
- [self ssTop popToReg: rcvrReg.
- self ssPop: 1.
- objectRepresentation
- genGetNumSlotsOf: rcvrReg into: resultReg;
- genConvertIntegerToSmallIntegerInReg: resultReg].
- "02 unchecked pointer basicSize"
- [3] -> "03 unchecked byte numBytes"
- [self ssTop popToReg: rcvrReg.
- self ssPop: 1.
- objectRepresentation
- genGetNumBytesOf: rcvrReg into: resultReg;
- genConvertIntegerToSmallIntegerInReg: resultReg].
- "04 unchecked short16Type format numShorts"
- "05 unchecked word32Type format numWords"
- "06 unchecked doubleWord64Type format numDoubleWords"
- [11] -> "11 unchecked fixed pointer basicNew"
- [self ssTop type ~= SSConstant ifTrue:
- [^EncounteredUnknownBytecode].
- (objectRepresentation
- genGetInstanceOfFixedClass: self ssTop constant
- into: resultReg
- initializingIf: self extBSpecifiesInitializeInstance) ~= 0 ifTrue:
- [^ShouldNotJIT]. "e.g. bad class"
- self ssPop: 1] .
- [20] -> "20 identityHash"
- [objectRepresentation genGetIdentityHash: rcvrReg resultReg: resultReg.
- self ssPop: 1] .
- "21 identityHash (SmallInteger)"
- "22 identityHash (Character)"
- "23 identityHash (SmallFloat64)"
- "24 identityHash (Behavior)"
- "30 immediateAsInteger (Character)
- 31 immediateAsInteger (SmallFloat64)
- 35 immediateAsFloat  (SmallInteger) "
- [30] ->
- [self ssTop popToReg: resultReg.
- objectRepresentation genConvertCharacterToSmallIntegerInReg: resultReg.
- self ssPop: 1].
- [35] ->
- [self assert: self processorHasDoublePrecisionFloatingPointSupport.
- self MoveR: rcvrReg R: TempReg.
- self genConvertSmallIntegerToIntegerInReg: TempReg.
- self ConvertR: TempReg Rd: DPFPReg0.
- self flag: #TODO. "Should never fail"
- self
- genAllocFloatValue: DPFPReg0
- into: resultReg
- scratchReg: TempReg
- scratchReg: NoReg. "scratch2 for V3 only"]
-  }
-
- otherwise:
- [^EncounteredUnknownBytecode].
- extB := 0.
- numExtB := 0.
- self ssPushRegister: resultReg.
- ^0!

Item was added:
+ ----- Method: SistaCogitClone>>genUnaryNewInlinePrimitive: (in category 'inline primitive unary generators') -----
+ genUnaryNewInlinePrimitive: primIndex
+ "1011 RawNew
+ literal which is a fixed-sized behavior => instance of the receiver with fields nilled out
+ 1012 RawNewNoInit
+ literal which is a fixed-sized behavior => instance of the receiver (Fields of returned value contain undefined data)"
+ | resultReg classObj |
+ self assert: (self ssTop type = SSConstant).
+ classObj := self ssTop constant.
+ self assert: (objectMemory isNonImmediate: classObj).
+ self assert: (coInterpreter objCouldBeClassObj: classObj).
+ self assert: (objectMemory isFixedSizePointerFormat: (objectMemory instSpecOfClassFormat: (objectMemory formatOfClass: classObj))).
+ objectMemory classTagForClass: classObj. "Ensure Behavior hash"
+ resultReg := self allocateRegNotConflictingWith: 0.
+ objectRepresentation genGetInstanceOfPointerClass: classObj into: resultReg initializingIf: primIndex = 11 numVariableSlots: 0.
+ self ssPop: 1.
+ ^self ssPushRegister: resultReg!

Item was added:
+ ----- Method: SistaCogitClone>>genUnaryPossibleRootInlinePrimitive (in category 'inline primitive unary generators') -----
+ genUnaryPossibleRootInlinePrimitive
+ "1041 possibleRoot
+ non-immediate, not a forwarder => receiver is returned (should be effect-only) (If old, becomes gray and remembered to allow many unchecked stores in a row afterwards)"
+ | topReg jmpDestYoung jmpAlreadyRemembered|
+ <var: #jmpDestYoung type: #'AbstractInstruction *'>
+ <var: #jmpAlreadyRemembered type: #'AbstractInstruction *'>
+ topReg := self allocateRegForStackEntryAt: 0 notConflictingWith: 0.
+ self ssTop popToReg: topReg.
+ self MoveCw: objectMemory storeCheckBoundary R: TempReg.
+ self CmpR: TempReg R: topReg.
+ jmpDestYoung := self JumpBelow: 0.
+ objectRepresentation checkRememberedInTrampoline ifFalse:
+ [jmpAlreadyRemembered := objectRepresentation genCheckRememberedBitOf: topReg scratch: TempReg].
+ objectRepresentation callStoreCheckTrampoline.
+ jmpDestYoung jmpTarget: self Label.
+ objectRepresentation checkRememberedInTrampoline ifFalse:
+ [jmpAlreadyRemembered jmpTarget: self Label].
+ self ssPop: 1.
+ ^self ssPushRegister: topReg!

Item was added:
+ ----- Method: SistaCogitClone>>genUnarySizeInlinePrimitive: (in category 'inline primitive unary generators') -----
+ genUnarySizeInlinePrimitive: primIndex
+ | rcvrReg resultReg |
+ self assert: (primIndex between: 1 and: 6).
+ rcvrReg := self allocateRegForStackEntryAt: 0 notConflictingWith: 0.
+ resultReg := self allocateRegNotConflictingWith: (self registerMaskFor: rcvrReg).
+ self ssTop popToReg: rcvrReg.
+ self ssPop: 1.
+ self ssPushRegister: resultReg.
+ primIndex caseOf: {
+ "1001 numSlots
+ pointer object => Smi between 0 and SmallInteger maxVal // 4 - 1 (Answers total size in pointer-sized slots)"
+ [1] -> [objectRepresentation
+ genGetNumSlotsOf: rcvrReg into: resultReg;
+ genConvertIntegerToSmallIntegerInReg: resultReg].
+ "1002 numBytes
+ byte object => Smi between 0 and SmallInteger maxVal - 9 (Includes compiled code)"
+ [2] -> [objectRepresentation
+ genGetNumBytesOf: rcvrReg into: resultReg;
+ genConvertIntegerToSmallIntegerInReg: resultReg].
+ "1003 numShorts
+ short object => Smi between 0 and SmallInteger maxVal - 9"
+ [3] -> [^EncounteredUnknownBytecode "not implemented"].
+ "1004 numWords
+ word object => Smi between 0 and SmallInteger maxVal - 9"
+ [5] -> [^EncounteredUnknownBytecode "not implemented"].
+ "1005 numDoubleWords
+ double word object => Smi between 0 and SmallInteger maxVal - 9"
+ [6] -> [^EncounteredUnknownBytecode "not implemented"].
+ }..
+ ^ 0!

Item was added:
+ ----- Method: SistaCogitClone>>genUnaryUnforwardInlinePrimitive (in category 'inline primitive unary generators') -----
+ genUnaryUnforwardInlinePrimitive
+ "1040 unforward
+ Anything => Not a forwarder"
+ | topReg |
+ topReg := self allocateRegForStackEntryAt: 0 notConflictingWith: 0.
+ self ssTop popToReg: topReg.
+ objectRepresentation genEnsureOopInRegNotForwarded: topReg scratchReg: TempReg.
+ self ssPop: 1.
+ ^self ssPushRegister: topReg!

Item was added:
+ ----- Method: SistaCogitClone>>genUnaryUnforwardNonImmediateInlinePrimitive (in category 'inline primitive unary generators') -----
+ genUnaryUnforwardNonImmediateInlinePrimitive
+ "1039 unforwardNonImmediate
+ non immediate => Not a forwarder"
+ | topReg |
+ topReg := self allocateRegForStackEntryAt: 0 notConflictingWith: 0.
+ self ssTop popToReg: topReg.
+ objectRepresentation genEnsureObjInRegNotForwarded: topReg scratchReg: TempReg.
+ self ssPop: 1.
+ ^self ssPushRegister: topReg!

Item was added:
+ ----- Method: SistaCogitClone>>maybeDealWithUnsafeJumpForDescriptor:pc:latestContinuation: (in category 'compile abstract instructions') -----
+ maybeDealWithUnsafeJumpForDescriptor: descriptor pc: pc latestContinuation: latestContinuation
+ "Mapped: 250 backjumpAlwaysInterrupt
+ Unmapped: 6000 backjumpNoInterrupt
+ 7016-7020 jumpWritable/Young
+ 8000-8003 type branches
+ In all cases the distance is an integer pushed on stack just before with pushIntegerLong:"
+ <var: #descriptor type: #'BytecodeDescriptor *'>
+ | distance targetPC byte01 byte02 newContinuation |
+ newContinuation := latestContinuation.
+ descriptor hasUnsafeJump ifTrue:
+ [ byte01 := objectMemory fetchByte: pc + 1 ofObject: methodObj.
+  byte02 := objectMemory fetchByte: pc + 2 ofObject: methodObj.
+  distance := self decodePushIntegerLongBefore: pc in: methodObj.
+  targetPC := pc + descriptor numBytes + distance.
+  descriptor isMapped
+ ifTrue: [ byte01 = 250 ifTrue:
+ [ "mapped always interrupt backjump"
+ self maybeCountFixup: descriptor.
+ self initializeFixupAt: targetPC ] ]
+ ifFalse:
+ [ byte02 >> 5 = 2r100 ifTrue:
+ [ "inlined sista primitive"
+ | prim |
+ prim := (byte02 bitAnd: 16r1F) << 8 + byte01.
+ prim >= 7000
+ ifTrue:
+ ["branch forward"
+ self maybeCountFixup: descriptor.
+ newContinuation := latestContinuation max: targetPC ]
+ ifFalse:
+ [prim >= 6000 ifTrue:
+ ["no interrupt back jump"
+ self maybeCountFixup: descriptor.
+ self initializeFixupAt: targetPC]]]]].
+ ^newContinuation!

Item was added:
+ ----- Method: SistaCogitClone>>maybeUnsafeJumpContinuation:at:for:in: (in category 'compile abstract instructions') -----
+ maybeUnsafeJumpContinuation: latestContinuation at: bcpc for: descriptor in: aMethodObj
+ <inline: true>
+ "Note: ignore backward jumps."
+ <var: #descriptor type: #'BytecodeDescriptor *'>
+ | distance targetPC byte01 byte02 newContinuation |
+ newContinuation := latestContinuation.
+ descriptor hasUnsafeJump ifTrue:
+ [ byte01 := objectMemory fetchByte: bcpc + 1 ofObject: aMethodObj.
+  byte02 := objectMemory fetchByte: bcpc + 2 ofObject: aMethodObj.
+  "pushIntegerLong"
+  distance := self decodePushIntegerLongBefore: bcpc in: methodObj.
+  targetPC := bcpc + descriptor numBytes + distance.
+  descriptor isMapped
+ ifFalse:
+ [ byte02 >> 5 = 2r100 ifTrue:
+ [ "inlined sista primitive"
+ | prim |
+ prim := (byte02 bitAnd: 16r1F) << 8 + byte01.
+ prim >= 7000
+ ifTrue:
+ ["branch forward"
+ newContinuation := latestContinuation max: targetPC ]]]].
+ ^newContinuation!

Item was changed:
  ----- Method: SistaRegisterAllocatingCogit class>>syncCodeWithSistaCogit (in category 'class initialization') -----
  syncCodeWithSistaCogit
  "Make sure that the SistaRegisterAllocatingCogit/SistaCogitClone combination is up-to-date w.r.t. SistaCogit.
  - SistaCogitClone should have all methods in SistaCogit except those implemented in SistaRegisterAllocatingCogit.
  This means that super sends in SistaCogitClone will be understood in SistaRegisterAllocatingCogit, not
+ RegisterAllocatingCogit.
- SistaRegisterAllocatingCogit.
  - newer methods in SistaCogitClone that are implemented in SistaRegisterAllocatingCogit should be moved up to
+ SistaRegisterAllocatingCogit because it means that we probably changed them in SistaCogitClone by mistake
- SistaRegisterAllocatingCogit becaude it means that we probably changed them in SistaCogitClone by mistake
  and forgot to copy them up.
  - the same goes for the class side, except for the intializeWithOptions: method which /should/ exist in both
  SistaRegisterAllocatingCogit and SistaCogitClone, because it runs this initialization."
  | syncAction |
  syncAction :=
  [self syncCodeIn: SistaCogit with: SistaCogitClone leavingUnchanged: nil.
  self syncCodeIn: SistaCogit class with: SistaCogitClone class leavingUnchanged: #initializeWithOptions:].
  ^(Smalltalk classNamed: #CurrentReadOnlySourceFiles)
  ifNil: syncAction
  ifNotNil: [:crosf| crosf cacheDuring: syncAction]!