[Vm-dev] VM Maker: VMMaker.oscog-eem.1594.mcz
commits at source.squeak.org
commits at source.squeak.org
Mon Dec 14 01:26:48 UTC 2015
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1594.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.1594
Author: eem
Time: 13 December 2015, 5:24:57.076 pm
UUID: 79da8b81-d1f3-469a-869c-16c79d12649a
Ancestors: VMMaker.oscog-eem.1593
Cogit:
Don't inline AndCq:R:R: because its translation contains a jump and hence won't work in a statement list expression (e.g. as in x86's genJumpSmallInteger:scratchReg:).
Nuke genJump[Not]SmallInteger:scratch: in favour of genJump[Not]SmallInteger:scratchReg:
Slang:
Eliminate leaves in statement lists generated as expressions.
=============== Diff against VMMaker.oscog-eem.1593 ===============
Item was removed:
- ----- Method: CogObjectRepresentation>>genJumpNotSmallInteger:scratch: (in category 'compile abstract instructions') -----
- genJumpNotSmallInteger: aRegister scratch: scratchReg
- "Generate a test for aRegister containing a SmallInteger and a jump if not, answering the jump.
- If necessary use scratch reg (since testing for SmallInteger may be destructive)."
- <returnTypeC: #'AbstractInstruction *'>
- | jumpNotInt |
- <inline: true>
- <var: 'jumpNotInt' type: #'AbstractInstruction *'>
- jumpNotInt := self genJumpNotSmallInteger: aRegister.
- jumpNotInt asInteger = UnimplementedOperation ifTrue:
- [cogit MoveR: aRegister R: scratchReg.
- jumpNotInt := self genJumpNotSmallIntegerInScratchReg: TempReg].
- ^jumpNotInt!
Item was changed:
----- Method: CogObjectRepresentation>>genJumpNotSmallInteger:scratchReg: (in category 'compile abstract instructions') -----
genJumpNotSmallInteger: aRegister scratchReg: scratch
"Generate a compare and branch to test if aRegister contains other than a SmallInteger.
Answer the jump. Use scratch if required. Subclasses will override if scratch is needed."
+ <inline: true>
- <returnTypeC: #'AbstractInstruction *'>
^self genJumpNotSmallInteger: aRegister!
Item was removed:
- ----- Method: CogObjectRepresentation>>genJumpSmallInteger:scratch: (in category 'compile abstract instructions') -----
- genJumpSmallInteger: aRegister scratch: scratchReg
- "Generate a test for aRegister containing a SmallInteger and a jump if so, answering the jump.
- If necessary use scratch reg (since testing for SmallInteger may be destructive)."
- <returnTypeC: #'AbstractInstruction *'>
- | jumpInt |
- <inline: true>
- <var: 'jumpInt' type: #'AbstractInstruction *'>
- jumpInt := self genJumpSmallInteger: aRegister.
- jumpInt asInteger = UnimplementedOperation ifTrue:
- [cogit MoveR: aRegister R: scratchReg.
- jumpInt := self genJumpSmallIntegerInScratchReg: TempReg].
- ^jumpInt!
Item was changed:
----- Method: CogObjectRepresentation>>genJumpSmallInteger:scratchReg: (in category 'compile abstract instructions') -----
genJumpSmallInteger: aRegister scratchReg: scratch
"Generate a compare and branch to test if aRegister contains a SmallInteger.
Answer the jump. Use scratch if required. Subclasses will override if scratch is needed."
- <returnTypeC: #'AbstractInstruction *'>
^self genJumpSmallInteger: aRegister!
Item was changed:
----- Method: CogObjectRepresentationFor32BitSpur>>genInnerPrimitiveAt: (in category 'primitive generators') -----
genInnerPrimitiveAt: retNoffset
"Implement the guts of primitiveAt"
| formatReg convertToIntAndReturn
jumpNotIndexable jumpImmediate jumpBadIndex
jumpIsBytes jumpIsShorts jumpIsWords jumpWordTooBig jumpIsArray jumpHasFixedFields jumpIsContext
jumpBytesOutOfBounds jumpShortsOutOfBounds jumpWordsOutOfBounds jumpArrayOutOfBounds jumpFixedFieldsOutOfBounds |
<inline: true>
"c.f. StackInterpreter>>stSizeOf: SpurMemoryManager>>lengthOf:format: fixedFieldsOf:format:length:"
<var: #jumpIsBytes type: #'AbstractInstruction *'>
<var: #jumpIsShorts type: #'AbstractInstruction *'>
<var: #jumpBadIndex type: #'AbstractInstruction *'>
<var: #jumpIsContext type: #'AbstractInstruction *'>
<var: #jumpImmediate type: #'AbstractInstruction *'>
<var: #jumpWordTooBig type: #'AbstractInstruction *'>
<var: #jumpNotIndexable type: #'AbstractInstruction *'>
<var: #jumpHasFixedFields type: #'AbstractInstruction *'>
<var: #convertToIntAndReturn type: #'AbstractInstruction *'>
<var: #jumpArrayOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpBytesOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpShortsOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpWordsOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpFixedFieldsOutOfBounds type: #'AbstractInstruction *'>
jumpImmediate := self genJumpImmediate: ReceiverResultReg.
cogit MoveR: Arg0Reg R: Arg1Reg.
+ jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg.
- jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratch: TempReg.
self genConvertSmallIntegerToIntegerInReg: Arg1Reg.
cogit SubCq: 1 R: Arg1Reg. "1-rel => 0-rel"
"formatReg := self formatOf: ReceiverResultReg"
self genGetFormatOf: ReceiverResultReg
into: (formatReg := SendNumArgsReg)
leastSignificantHalfOfBaseHeaderIntoScratch: TempReg.
self genGetNumSlotsOf: ReceiverResultReg into: ClassReg.
"dispatch on format in a combination of highest dynamic frequency order first and convenience.
0 = 0 sized objects (UndefinedObject True False et al)
1 = non-indexable objects with inst vars (Point et al)
2 = indexable objects with no inst vars (Array et al)
3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al)
4 = weak indexable objects with inst vars (WeakArray et al)
5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron)
6 unused, reserved for exotic pointer objects?
7 Forwarded Object, 1st field is pointer, rest of fields are ignored
8 unused, reserved for exotic non-pointer objects?
9 (?) 64-bit indexable
10 - 11 32-bit indexable
12 - 15 16-bit indexable
16 - 23 byte indexable
24 - 31 compiled method"
cogit CmpCq: objectMemory firstByteFormat R: formatReg.
jumpIsBytes := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory arrayFormat R: formatReg.
jumpIsArray := cogit JumpZero: 0.
jumpNotIndexable := cogit JumpBelow: 0.
cogit CmpCq: objectMemory weakArrayFormat R: formatReg.
jumpHasFixedFields := cogit JumpBelowOrEqual: 0.
cogit CmpCq: objectMemory firstShortFormat R: formatReg.
jumpIsShorts := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory firstLongFormat R: formatReg.
jumpIsWords := cogit JumpAboveOrEqual: 0.
"For now ignore 64-bit indexability."
jumpNotIndexable jmpTarget: cogit Label.
jumpNotIndexable := cogit Jump: 0.
jumpIsBytes jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord R: ClassReg).
cogit AndCq: objectMemory wordSize - 1 R: formatReg.
cogit SubR: formatReg R: ClassReg;
CmpR: Arg1Reg R: ClassReg.
jumpBytesOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize R: Arg1Reg.
cogit backEnd byteReadsZeroExtend
ifTrue:
[cogit MoveXbr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg]
ifFalse:
[cogit "formatReg already contains a value <= 16r1f, so no need to zero it"
MoveXbr: Arg1Reg R: ReceiverResultReg R: formatReg;
MoveR: formatReg R: ReceiverResultReg].
convertToIntAndReturn := cogit Label.
self genConvertIntegerToSmallIntegerInReg: ReceiverResultReg.
cogit RetN: retNoffset.
jumpIsShorts jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: ClassReg).
cogit AndCq: 1 R: formatReg.
cogit SubR: formatReg R: ClassReg;
CmpR: Arg1Reg R: ClassReg.
jumpShortsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddR: Arg1Reg R: ReceiverResultReg.
cogit MoveM16: objectMemory baseHeaderSize r: ReceiverResultReg R: ReceiverResultReg.
cogit Jump: convertToIntAndReturn.
jumpIsWords jmpTarget:
(cogit CmpR: Arg1Reg R: ClassReg).
jumpWordsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
cogit MoveXwr: Arg1Reg R: ReceiverResultReg R: TempReg.
cogit SubCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
jumpWordTooBig := self jumpNotSmallIntegerUnsignedValueInRegister: TempReg.
cogit MoveR: TempReg R: ReceiverResultReg.
cogit Jump: convertToIntAndReturn.
jumpHasFixedFields jmpTarget:
(cogit AndCq: objectMemory classIndexMask R: TempReg).
cogit MoveR: TempReg R: formatReg.
cogit CmpCq: ClassMethodContextCompactIndex R: TempReg.
jumpIsContext := cogit JumpZero: 0.
cogit PushR: ClassReg.
self genGetClassObjectOfClassIndex: formatReg into: ClassReg scratchReg: TempReg.
self genLoadSlot: InstanceSpecificationIndex sourceReg: ClassReg destReg: formatReg.
cogit PopR: ClassReg.
self genConvertSmallIntegerToIntegerInReg: formatReg.
cogit
AndCq: objectMemory fixedFieldsOfClassFormatMask R: formatReg;
SubR: formatReg R: ClassReg;
CmpR: Arg1Reg R: ClassReg.
jumpFixedFieldsOutOfBounds := cogit JumpBelowOrEqual: 0.
"index is (formatReg (fixed fields) + Arg1Reg (0-rel index)) * wordSize + baseHeaderSize"
cogit AddR: formatReg R: Arg1Reg.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
cogit MoveXwr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg.
cogit RetN: retNoffset.
jumpIsArray jmpTarget:
(cogit CmpR: Arg1Reg R: ClassReg).
jumpArrayOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
cogit MoveXwr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg.
cogit RetN: retNoffset.
jumpFixedFieldsOutOfBounds jmpTarget:
(jumpArrayOutOfBounds jmpTarget:
(jumpBytesOutOfBounds jmpTarget:
(jumpShortsOutOfBounds jmpTarget:
(jumpWordsOutOfBounds jmpTarget:
(jumpWordTooBig jmpTarget:
(jumpNotIndexable jmpTarget:
(jumpIsContext jmpTarget:
(jumpBadIndex jmpTarget:
(jumpImmediate jmpTarget: cogit Label))))))))).
^0!
Item was changed:
----- Method: CogObjectRepresentationFor64BitSpur>>genInnerPrimitiveAt: (in category 'primitive generators') -----
genInnerPrimitiveAt: retNoffset
"Implement the guts of primitiveAt"
| formatReg convertToIntAndReturn
jumpNotIndexable jumpImmediate jumpBadIndex
jumpIsBytes jumpIsShorts jumpIsWords jumpIsArray jumpHasFixedFields jumpIsContext
jumpBytesOutOfBounds jumpShortsOutOfBounds jumpWordsOutOfBounds jumpArrayOutOfBounds jumpFixedFieldsOutOfBounds |
<inline: true>
"c.f. StackInterpreter>>stSizeOf: SpurMemoryManager>>lengthOf:format: fixedFieldsOf:format:length:"
<var: #jumpIsBytes type: #'AbstractInstruction *'>
<var: #jumpIsShorts type: #'AbstractInstruction *'>
<var: #jumpBadIndex type: #'AbstractInstruction *'>
<var: #jumpIsContext type: #'AbstractInstruction *'>
<var: #jumpImmediate type: #'AbstractInstruction *'>
<var: #jumpNotIndexable type: #'AbstractInstruction *'>
<var: #jumpHasFixedFields type: #'AbstractInstruction *'>
<var: #convertToIntAndReturn type: #'AbstractInstruction *'>
<var: #jumpArrayOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpBytesOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpShortsOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpWordsOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpFixedFieldsOutOfBounds type: #'AbstractInstruction *'>
jumpImmediate := self genJumpImmediate: ReceiverResultReg.
cogit MoveR: Arg0Reg R: Arg1Reg.
+ jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg.
- jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratch: TempReg.
self genConvertSmallIntegerToIntegerInReg: Arg1Reg.
cogit SubCq: 1 R: Arg1Reg. "1-rel => 0-rel"
"formatReg := self formatOf: ReceiverResultReg"
self genGetFormatOf: ReceiverResultReg
into: (formatReg := SendNumArgsReg)
leastSignificantHalfOfBaseHeaderIntoScratch: TempReg.
self genGetNumSlotsOf: ReceiverResultReg into: ClassReg.
"dispatch on format in a combination of highest dynamic frequency order first and convenience.
0 = 0 sized objects (UndefinedObject True False et al)
1 = non-indexable objects with inst vars (Point et al)
2 = indexable objects with no inst vars (Array et al)
3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al)
4 = weak indexable objects with inst vars (WeakArray et al)
5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron)
6 unused, reserved for exotic pointer objects?
7 Forwarded Object, 1st field is pointer, rest of fields are ignored
8 unused, reserved for exotic non-pointer objects?
9 (?) 64-bit indexable
10 - 11 32-bit indexable
12 - 15 16-bit indexable
16 - 23 byte indexable
24 - 31 compiled method"
cogit CmpCq: objectMemory firstByteFormat R: formatReg.
jumpIsBytes := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory arrayFormat R: formatReg.
jumpIsArray := cogit JumpZero: 0.
jumpNotIndexable := cogit JumpBelow: 0.
cogit CmpCq: objectMemory weakArrayFormat R: formatReg.
jumpHasFixedFields := cogit JumpBelowOrEqual: 0.
cogit CmpCq: objectMemory firstShortFormat R: formatReg.
jumpIsShorts := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory firstLongFormat R: formatReg.
jumpIsWords := cogit JumpAboveOrEqual: 0.
"For now ignore 64-bit indexability."
jumpNotIndexable jmpTarget: cogit Label.
jumpNotIndexable := cogit Jump: 0.
jumpIsBytes jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord R: ClassReg).
cogit AndCq: objectMemory wordSize - 1 R: formatReg.
cogit SubR: formatReg R: ClassReg;
CmpR: Arg1Reg R: ClassReg.
jumpBytesOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize R: Arg1Reg.
cogit backEnd byteReadsZeroExtend
ifTrue:
[cogit MoveXbr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg]
ifFalse:
[cogit "formatReg already contains a value <= 16r1f, so no need to zero it"
MoveXbr: Arg1Reg R: ReceiverResultReg R: formatReg;
MoveR: formatReg R: ReceiverResultReg].
convertToIntAndReturn := cogit Label.
self genConvertIntegerToSmallIntegerInReg: ReceiverResultReg.
cogit RetN: retNoffset.
jumpIsShorts jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: ClassReg).
cogit AndCq: 1 R: formatReg.
cogit SubR: formatReg R: ClassReg;
CmpR: Arg1Reg R: ClassReg.
jumpShortsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddR: Arg1Reg R: ReceiverResultReg.
cogit MoveM16: objectMemory baseHeaderSize r: ReceiverResultReg R: ReceiverResultReg.
cogit Jump: convertToIntAndReturn.
jumpIsWords jmpTarget:
(cogit CmpR: Arg1Reg R: ClassReg).
jumpWordsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize >> (objectMemory shiftForWord - 1) R: Arg1Reg.
cogit MoveX32r: Arg1Reg R: ReceiverResultReg R: TempReg.
cogit MoveR: TempReg R: ReceiverResultReg.
cogit Jump: convertToIntAndReturn.
jumpHasFixedFields jmpTarget:
(cogit AndCq: objectMemory classIndexMask R: TempReg).
cogit MoveR: TempReg R: formatReg.
cogit CmpCq: ClassMethodContextCompactIndex R: TempReg.
jumpIsContext := cogit JumpZero: 0.
self genGetClassObjectOfClassIndex: formatReg into: Scratch0Reg scratchReg: TempReg.
self genLoadSlot: InstanceSpecificationIndex sourceReg: Scratch0Reg destReg: formatReg.
self genConvertSmallIntegerToIntegerInReg: formatReg.
cogit
AndCq: objectMemory fixedFieldsOfClassFormatMask R: formatReg;
SubR: formatReg R: ClassReg;
CmpR: Arg1Reg R: ClassReg.
jumpFixedFieldsOutOfBounds := cogit JumpBelowOrEqual: 0.
"index is (formatReg (fixed fields) + Arg1Reg (0-rel index)) * wordSize + baseHeaderSize"
cogit AddR: formatReg R: Arg1Reg.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
cogit MoveXwr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg.
cogit RetN: retNoffset.
jumpIsArray jmpTarget:
(cogit CmpR: Arg1Reg R: ClassReg).
jumpArrayOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
cogit MoveXwr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg.
cogit RetN: retNoffset.
jumpFixedFieldsOutOfBounds jmpTarget:
(jumpArrayOutOfBounds jmpTarget:
(jumpBytesOutOfBounds jmpTarget:
(jumpShortsOutOfBounds jmpTarget:
(jumpWordsOutOfBounds jmpTarget:
(jumpNotIndexable jmpTarget:
(jumpIsContext jmpTarget:
(jumpBadIndex jmpTarget:
(jumpImmediate jmpTarget: cogit Label)))))))).
^0!
Item was changed:
----- Method: CogObjectRepresentationFor64BitSpur>>genInnerPrimitiveNewWithArg: (in category 'primitive generators') -----
genInnerPrimitiveNewWithArg: retNoffset
"Implement primitiveNewWithArg for convenient cases:
- the receiver has a hash
- the receiver is variable and not compiled method
- single word header/num slots < numSlotsMask
- the result fits in eden
See superclass method for dynamic frequencies of formats.
For the moment we implement only arrayFormat, firstByteFormat & firstLongFormat"
| headerReg fillReg instSpecReg byteSizeReg maxSlots
jumpArrayTooBig jumpByteTooBig jumpLongTooBig
jumpArrayFormat jumpByteFormat jumpBytePrepDone jumpLongPrepDone
jumpUnhashed jumpNElementsNonInt jumpFailCuzFixed jumpNoSpace jumpHasSlots fillLoop skip |
<var: 'skip' type: #'AbstractInstruction *'>
<var: 'fillLoop' type: #'AbstractInstruction *'>
<var: 'jumpHasSlots' type: #'AbstractInstruction *'>
<var: 'jumpNoSpace' type: #'AbstractInstruction *'>
<var: 'jumpUnhashed' type: #'AbstractInstruction *'>
<var: 'jumpByteFormat' type: #'AbstractInstruction *'>
<var: 'jumpByteTooBig' type: #'AbstractInstruction *'>
<var: 'jumpLongTooBig' type: #'AbstractInstruction *'>
<var: 'jumpArrayFormat' type: #'AbstractInstruction *'>
<var: 'jumpArrayTooBig' type: #'AbstractInstruction *'>
<var: 'jumpFailCuzFixed' type: #'AbstractInstruction *'>
<var: 'jumpBytePrepDone' type: #'AbstractInstruction *'>
<var: 'jumpLongPrepDone' type: #'AbstractInstruction *'>
<var: 'jumpNElementsNonInt' type: #'AbstractInstruction *'>
"header will contain classIndex/class's hash & format & numSlots/fixed size"
headerReg := SendNumArgsReg.
"Assume there's an available scratch register on 64-bit machines. This holds the saved numFixedFileds and then the value to fill with"
fillReg := Scratch0Reg.
self assert: (cogit backEnd concreteRegister: fillReg) > 0.
"inst spec will hold class's instance specification and then byte size"
instSpecReg := byteSizeReg := ClassReg.
"The max slots we'll allocate here are those for a single header"
maxSlots := objectMemory numSlotsMask - 1.
"get freeStart as early as possible so as not to wait later..."
cogit MoveAw: objectMemory freeStartAddress R: Arg1Reg.
"get class's hash & fail if 0"
self genGetHashFieldNonImmOf: ReceiverResultReg into: headerReg.
jumpUnhashed := cogit JumpZero: 0.
"get index and fail if not a +ve integer"
+ jumpNElementsNonInt := self genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg.
- jumpNElementsNonInt := self genJumpNotSmallInteger: Arg0Reg scratch: TempReg.
"get class's format inst var for inst spec (format field)"
self genLoadSlot: InstanceSpecificationIndex sourceReg: ReceiverResultReg destReg: instSpecReg.
cogit LogicalShiftRightCq: objectMemory fixedFieldsFieldWidth + self numSmallIntegerTagBits R: instSpecReg.
cogit AndCq: objectMemory formatMask R: instSpecReg.
"Add format to classIndex/format header now"
cogit MoveR: instSpecReg R: TempReg.
cogit LogicalShiftLeftCq: objectMemory formatShift R: TempReg.
cogit AddR: TempReg R: headerReg.
"get integer value of num fields in fillReg now"
cogit MoveR: Arg0Reg R: fillReg.
self genConvertSmallIntegerToIntegerInReg: fillReg.
"dispatch on format, failing if not variable or if compiled method"
cogit CmpCq: objectMemory arrayFormat R: instSpecReg.
jumpArrayFormat := cogit JumpZero: 0.
cogit CmpCq: objectMemory firstByteFormat R: instSpecReg.
jumpByteFormat := cogit JumpZero: 0.
cogit CmpCq: objectMemory firstLongFormat R: instSpecReg.
jumpFailCuzFixed := cogit JumpNonZero: 0.
cogit CmpCq: (objectMemory integerObjectOf: maxSlots * 2) R: Arg0Reg.
jumpLongTooBig := cogit JumpAbove: 0.
"save num elements/slot size to instSpecReg"
cogit MoveR: fillReg R: instSpecReg.
"compute odd bits and add into headerReg; oddBits := 2 - nElements bitAnd: 1"
cogit MoveCq: objectMemory wordSize / 4 R: TempReg.
cogit SubR: instSpecReg R: TempReg.
cogit AndCq: objectMemory wordSize / 4 - 1 R: TempReg.
cogit LogicalShiftLeftCq: objectMemory formatShift R: TempReg.
cogit AddR: TempReg R: headerReg.
"round up num elements to numSlots in instSpecReg"
cogit AddCq: objectMemory wordSize / 4 - 1 R: instSpecReg.
cogit LogicalShiftRightCq: objectMemory shiftForWord - 2 R: instSpecReg.
cogit MoveCq: 0 R: fillReg.
jumpLongPrepDone := cogit Jump: 0. "go allocate"
jumpByteFormat jmpTarget:
(cogit CmpCq: (objectMemory integerObjectOf: maxSlots * objectMemory wordSize) R: Arg0Reg).
jumpByteTooBig := cogit JumpAbove: 0.
"save num elements to instSpecReg"
cogit MoveR: fillReg R: instSpecReg.
"compute odd bits and add into headerReg; oddBits := 4 - nElements bitAnd: 3"
cogit MoveCq: objectMemory wordSize R: TempReg.
cogit SubR: instSpecReg R: TempReg.
cogit AndCq: objectMemory wordSize - 1 R: TempReg.
cogit LogicalShiftLeftCq: objectMemory formatShift R: TempReg.
cogit AddR: TempReg R: headerReg.
"round up num elements to numSlots in instSpecReg"
cogit AddCq: objectMemory wordSize - 1 R: instSpecReg.
cogit LogicalShiftRightCq: objectMemory shiftForWord R: instSpecReg.
cogit MoveCq: 0 R: fillReg.
jumpBytePrepDone := cogit Jump: 0. "go allocate"
jumpArrayFormat jmpTarget:
(cogit CmpCq: (objectMemory integerObjectOf: maxSlots) R: Arg0Reg).
jumpArrayTooBig := cogit JumpAbove: 0.
"save num elements/slot size to instSpecReg"
cogit MoveR: fillReg R: instSpecReg.
cogit MoveCq: objectMemory nilObject R: fillReg.
"fall through to allocate"
jumpBytePrepDone jmpTarget:
(jumpLongPrepDone jmpTarget: cogit Label).
"store numSlots to headerReg"
cogit MoveR: instSpecReg R: TempReg.
cogit LogicalShiftLeftCq: objectMemory numSlotsFullShift R: TempReg.
cogit AddR: TempReg R: headerReg.
"compute byte size; remember 0-sized objects still need 1 slot."
cogit CmpCq: 0 R: byteSizeReg. "a.k.a. instSpecReg"
jumpHasSlots := cogit JumpNonZero: 0.
cogit MoveCq: objectMemory baseHeaderSize * 2 R: byteSizeReg.
skip := cogit Jump: 0.
jumpHasSlots jmpTarget:
(cogit AddCq: objectMemory baseHeaderSize / objectMemory wordSize R: byteSizeReg).
cogit LogicalShiftLeftCq: objectMemory shiftForWord R: byteSizeReg.
skip jmpTarget:
"check if allocation fits"
(cogit AddR: Arg1Reg R: byteSizeReg).
cogit CmpCq: objectMemory getScavengeThreshold R: byteSizeReg.
jumpNoSpace := cogit JumpAboveOrEqual: 0.
"get result, increment freeStart and write it back. Arg1Reg holds new freeStart, the limit of the object"
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit MoveR: byteSizeReg Aw: objectMemory freeStartAddress.
"write other half of header (numSlots/0 identityHash)"
cogit MoveR: headerReg Mw: 0 r: ReceiverResultReg.
"now fill"
cogit LoadEffectiveAddressMw: objectMemory baseHeaderSize r: ReceiverResultReg R: Arg1Reg.
fillLoop :=
cogit MoveR: fillReg Mw: 0 r: Arg1Reg.
cogit AddCq: 8 R: Arg1Reg.
cogit CmpR: Arg1Reg R: byteSizeReg.
cogit JumpAbove: fillLoop.
cogit RetN: retNoffset.
jumpNoSpace jmpTarget:
(jumpUnhashed jmpTarget:
(jumpFailCuzFixed jmpTarget:
(jumpArrayTooBig jmpTarget:
(jumpByteTooBig jmpTarget:
(jumpLongTooBig jmpTarget:
(jumpNElementsNonInt jmpTarget: cogit Label)))))).
^0!
Item was changed:
----- Method: CogObjectRepresentationForSpur>>genInnerPrimitiveAsCharacter:inReg: (in category 'primitive generators') -----
genInnerPrimitiveAsCharacter: retNOffset inReg: reg
| jumpNotInt jumpOutOfRange |
<var: 'jumpNotInt' type: #'AbstractInstruction *'>
<var: 'jumpOutOfRange' type: #'AbstractInstruction *'>
reg ~= ReceiverResultReg ifTrue:
+ [jumpNotInt := self genJumpNotSmallInteger: reg scratchReg: TempReg].
- [jumpNotInt := self genJumpNotSmallInteger: reg scratch: TempReg].
cogit MoveR: reg R: TempReg.
self genConvertSmallIntegerToIntegerInReg: TempReg.
cogit CmpCq: 1 << 30 - 1 R: TempReg.
jumpOutOfRange := cogit JumpAbove: 0.
self genConvertSmallIntegerToCharacterInReg: reg.
reg ~= ReceiverResultReg ifTrue:
[cogit MoveR: reg R: ReceiverResultReg].
cogit RetN: retNOffset.
jumpOutOfRange jmpTarget: cogit Label.
reg ~= ReceiverResultReg ifTrue:
[jumpNotInt jmpTarget: jumpOutOfRange getJmpTarget].
^0!
Item was changed:
----- Method: CogObjectRepresentationForSpur>>genInnerPrimitiveObjectAt: (in category 'primitive generators') -----
genInnerPrimitiveObjectAt: retNOffset
| headerReg
jumpBadIndex jumpNotCogMethod jumpBounds jumpNotHeaderIndex |
<var: #jumpBounds type: #'AbstractInstruction *'>
<var: #jumpBadIndex type: #'AbstractInstruction *'>
<var: #jumpNotCogMethod type: #'AbstractInstruction *'>
<var: #jumpNotHeaderIndex type: #'AbstractInstruction *'>
+ jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg.
- jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratch: TempReg.
"get header into Arg1Reg..."
cogit MoveMw: objectMemory baseHeaderSize r: ReceiverResultReg R: (headerReg := Arg1Reg).
+ jumpNotCogMethod := self genJumpSmallInteger: headerReg scratchReg: TempReg.
- jumpNotCogMethod := self genJumpSmallInteger: headerReg scratch: TempReg.
cogit MoveMw: (cogit offset: CogMethod of: #methodHeader) r: headerReg R: headerReg.
jumpNotCogMethod jmpTarget: (cogit
CmpCq: (objectMemory integerObjectOf: 1) R: Arg0Reg).
jumpNotHeaderIndex := cogit JumpNonZero: 0.
cogit
MoveR: headerReg R: ReceiverResultReg;
RetN: retNOffset.
jumpNotHeaderIndex jmpTarget: (cogit
AndCq: (objectMemory integerObjectOf: coInterpreter alternateHeaderNumLiteralsMask) R: headerReg).
cogit
SubCq: (objectMemory integerObjectOf: 1) - objectMemory smallIntegerTag R: Arg0Reg;
CmpR: headerReg R: Arg0Reg.
jumpBounds := cogit JumpAbove: 0.
self genConvertSmallIntegerToIntegerInReg: Arg0Reg.
cogit
AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg0Reg;
MoveXwr: Arg0Reg R: ReceiverResultReg R: ReceiverResultReg;
RetN: retNOffset.
jumpBounds jmpTarget: (cogit
AddCq: (objectMemory integerObjectOf: 1) - objectMemory smallIntegerTag R: Arg0Reg).
jumpBadIndex jmpTarget: cogit Label.
^CompletePrimitive!
Item was changed:
----- Method: CogObjectRepresentationForSpur>>genInnerPrimitiveStringAt: (in category 'primitive generators') -----
genInnerPrimitiveStringAt: retNoffset
"Implement the guts of primitiveStringAt; dispatch on size"
| formatReg jumpNotIndexable jumpBadIndex done
jumpIsBytes jumpIsShorts jumpIsWords jumpWordTooBig
jumpBytesOutOfBounds jumpShortsOutOfBounds jumpWordsOutOfBounds |
<inline: true>
"c.f. StackInterpreter>>stSizeOf: SpurMemoryManager>>lengthOf:format: fixedFieldsOf:format:length:"
<var: #done type: #'AbstractInstruction *'>
<var: #jumpIsBytes type: #'AbstractInstruction *'>
<var: #jumpIsShorts type: #'AbstractInstruction *'>
<var: #jumpIsWords type: #'AbstractInstruction *'>
<var: #jumpBadIndex type: #'AbstractInstruction *'>
<var: #jumpWordTooBig type: #'AbstractInstruction *'>
<var: #jumpNotIndexable type: #'AbstractInstruction *'>
<var: #jumpBytesOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpShortsOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpWordsOutOfBounds type: #'AbstractInstruction *'>
cogit MoveR: Arg0Reg R: Arg1Reg.
+ jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg.
- jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratch: TempReg.
self genConvertSmallIntegerToIntegerInReg: Arg1Reg.
cogit SubCq: 1 R: Arg1Reg. "1-rel => 0-rel"
self genGetFormatOf: ReceiverResultReg
into: (formatReg := SendNumArgsReg)
leastSignificantHalfOfBaseHeaderIntoScratch: NoReg.
self genGetNumSlotsOf: ReceiverResultReg into: ClassReg.
"dispatch on format in a combination of highest dynamic frequency order first and convenience.
0 = 0 sized objects (UndefinedObject True False et al)
1 = non-indexable objects with inst vars (Point et al)
2 = indexable objects with no inst vars (Array et al)
3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al)
4 = weak indexable objects with inst vars (WeakArray et al)
5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron)
6 unused, reserved for exotic pointer objects?
7 Forwarded Object, 1st field is pointer, rest of fields are ignored
8 unused, reserved for exotic non-pointer objects?
9 (?) 64-bit indexable
10 - 11 32-bit indexable
12 - 15 16-bit indexable
16 - 23 byte indexable
24 - 31 compiled method"
cogit CmpCq: objectMemory firstByteFormat R: formatReg.
jumpIsBytes := cogit JumpGreaterOrEqual: 0.
cogit CmpCq: objectMemory firstShortFormat R: formatReg.
jumpIsShorts := cogit JumpGreaterOrEqual: 0.
cogit CmpCq: objectMemory firstLongFormat R: formatReg.
jumpIsWords := cogit JumpGreaterOrEqual: 0.
jumpNotIndexable := cogit Jump: 0.
jumpIsBytes jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord R: ClassReg).
cogit AndCq: objectMemory wordSize - 1 R: formatReg.
cogit SubR: formatReg R: ClassReg;
CmpR: Arg1Reg R: ClassReg.
jumpBytesOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize R: Arg1Reg.
cogit MoveXbr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg.
cogit backEnd byteReadsZeroExtend ifFalse:
[cogit AndCq: 255 R: ReceiverResultReg].
done := cogit Label.
self genConvertIntegerToCharacterInReg: ReceiverResultReg.
cogit RetN: retNoffset.
jumpIsShorts jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: ClassReg).
cogit AndCq: 1 R: formatReg.
cogit SubR: formatReg R: ClassReg;
CmpR: Arg1Reg R: ClassReg.
jumpShortsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddR: Arg1Reg R: ReceiverResultReg.
cogit MoveM16: objectMemory baseHeaderSize r: ReceiverResultReg R: ReceiverResultReg.
cogit Jump: done.
jumpIsWords jmpTarget:
(cogit CmpR: Arg1Reg R: ClassReg).
jumpWordsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
cogit MoveXwr: Arg1Reg R: ReceiverResultReg R: TempReg.
cogit SubCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
jumpWordTooBig := self jumpNotCharacterUnsignedValueInRegister: TempReg.
cogit MoveR: TempReg R: ReceiverResultReg.
cogit Jump: done.
jumpBytesOutOfBounds jmpTarget:
(jumpShortsOutOfBounds jmpTarget:
(jumpWordsOutOfBounds jmpTarget:
(jumpWordTooBig jmpTarget:
(jumpNotIndexable jmpTarget:
(jumpBadIndex jmpTarget: cogit Label))))).
^0!
Item was changed:
----- Method: Cogit>>AndCq:R:R: (in category 'abstract instructions') -----
AndCq: quickConstant R: srcReg R: destReg
+ <inline: false>
- <inline: true>
<returnTypeC: #'AbstractInstruction *'>
| first |
<var: 'first' type: #'AbstractInstruction *'>
backEnd hasThreeAddressArithmetic ifTrue:
[^self gen: AndCqRR quickConstant: quickConstant operand: srcReg operand: destReg].
srcReg = destReg ifTrue:
[^self gen: AndCqR quickConstant: quickConstant operand: destReg.].
first := self gen: MoveRR operand: srcReg operand: destReg.
self gen: AndCqR quickConstant: quickConstant operand: destReg.
^first!
Item was changed:
----- Method: OutOfLineLiteralsManager>>checkQuickConstant:forInstruction: (in category 'compile abstract instructions') -----
checkQuickConstant: literal forInstruction: anInstruction
<var: #anInstruction type: #'AbstractInstruction *'>
<returnTypeC: #'AbstractInstruction *'>
+ <inline: true>
anInstruction usesOutOfLineLiteral ifTrue:
+ [anInstruction dependent: (self locateLiteral: (self cCode: [literal] inSmalltalk: [literal bitAnd: 1 << (objectMemory wordSize * 8) - 1]))].
- [anInstruction dependent: (self locateLiteral: (self cCode: [literal] inSmalltalk: [literal bitAnd: 16rFFFFFFFF]))].
^anInstruction!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genDoubleArithmetic:preOpCheck: (in category 'primitive generators') -----
genDoubleArithmetic: arithmeticOperator preOpCheck: preOpCheckOrNil
"Receiver and arg in registers.
Stack looks like
return address"
<var: #preOpCheckOrNil declareC: 'AbstractInstruction *(*preOpCheckOrNil)(int rcvrReg, int argReg)'>
| jumpFailClass jumpFailClass2 jumpFailAlloc jumpFailCheck jumpImmediate jumpNonInt doOp |
<var: #jumpFailClass type: #'AbstractInstruction *'>
<var: #jumpFailClass2 type: #'AbstractInstruction *'>
<var: #jumpFailAlloc type: #'AbstractInstruction *'>
<var: #jumpImmediate type: #'AbstractInstruction *'>
<var: #jumpNonInt type: #'AbstractInstruction *'>
<var: #jumpFailCheck type: #'AbstractInstruction *'>
<var: #doOp type: #'AbstractInstruction *'>
objectRepresentation genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0.
self MoveR: Arg0Reg R: ClassReg.
jumpImmediate := objectRepresentation genJumpImmediate: Arg0Reg.
objectRepresentation genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg.
objectRepresentation genCmpClassFloatCompactIndexR: SendNumArgsReg.
jumpFailClass := self JumpNonZero: 0.
objectRepresentation genGetDoubleValueOf: Arg0Reg into: DPFPReg1.
doOp := self Label.
preOpCheckOrNil ifNotNil:
[jumpFailCheck := self perform: preOpCheckOrNil with: DPFPReg0 with: DPFPReg1].
self gen: arithmeticOperator operand: DPFPReg1 operand: DPFPReg0.
jumpFailAlloc := objectRepresentation
genAllocFloatValue: DPFPReg0
into: SendNumArgsReg
scratchReg: ClassReg
scratchReg: TempReg.
self MoveR: SendNumArgsReg R: ReceiverResultReg.
self RetN: 0.
jumpImmediate jmpTarget: self Label.
objectRepresentation maybeGenConvertIfSmallFloatIn: Arg0Reg scratchReg: TempReg into: DPFPReg1 andJumpTo: doOp.
objectRepresentation smallIntegerIsOnlyImmediateType ifFalse:
+ [jumpNonInt := objectRepresentation genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg].
- [jumpNonInt := objectRepresentation genJumpNotSmallInteger: Arg0Reg scratch: TempReg].
objectRepresentation genConvertSmallIntegerToIntegerInReg: ClassReg.
self ConvertR: ClassReg Rd: DPFPReg1.
self Jump: doOp.
"We need to push the register args on two paths; this one and the interpreter primitive path.
But the interpreter primitive path won't unless regArgsHaveBeenPushed is false."
self assert: methodOrBlockNumArgs <= self numRegArgs.
jumpFailClass jmpTarget: self Label.
objectRepresentation smallIntegerIsOnlyImmediateType ifFalse:
[jumpNonInt jmpTarget: jumpFailClass getJmpTarget].
preOpCheckOrNil ifNotNil:
[jumpFailCheck jmpTarget: jumpFailClass getJmpTarget].
backEnd genPushRegisterArgsForNumArgs: methodOrBlockNumArgs scratchReg: SendNumArgsReg.
jumpFailClass2 := self Jump: 0.
jumpFailAlloc jmpTarget: self Label.
self compileFallbackToInterpreterPrimitive: 0.
jumpFailClass2 jmpTarget: self Label.
^0!
Item was changed:
----- Method: TReturnNode>>emitCCodeOn:level:generator: (in category 'C code generation') -----
emitCCodeOn: aStream level: level generator: aCodeGen
(expression isSwitch
or: [expression isCaseStmt]) ifTrue:
[^expression emitCCodeOn: aStream addToEndOfCases: self level: level generator: aCodeGen].
(expression isSend and: [expression isValueExpansion]) ifTrue:
[^self emitValueExpansionOn: aStream level: level generator: aCodeGen].
'void' = aCodeGen currentMethod returnType ifTrue: "If the function is void, don't say 'return x' instead say ' x; return' "
[expression isLeaf ifFalse:
[expression emitCCodeAsArgumentOn: aStream level: level generator: aCodeGen.
aStream nextPut: $;; crtab: level].
aStream nextPutAll: 'return'.
^self].
aStream nextPutAll: 'return '.
+ expression
+ emitCCodeAsArgumentOn: aStream
+ level: (expression isStmtList ifTrue: [level + 1] ifFalse: [level])
+ generator: aCodeGen!
- expression emitCCodeAsArgumentOn: aStream level: level generator: aCodeGen!
Item was changed:
----- Method: TStmtListNode>>emitCCodeAsArgumentOn:level:generator: (in category 'C code generation') -----
emitCCodeAsArgumentOn: aStream level: level generator: aCodeGen
+ | size |
+ (size := statements size) = 1 ifTrue:
-
- | statementWasComment |
- statements size = 1 ifTrue:
[^statements first emitCCodeAsArgumentOn: aStream level: level generator: aCodeGen].
- statementWasComment := false.
aStream nextPut: $(. "N.B. Comma binds weakest of all C operators."
+ statements withIndexDo:
+ [:s :idx| | p1 p2 |
+ p1 := aStream position.
+ s emitCCommentOn: aStream level: level.
+ (s isLeaf and: [s isLabel not and: [idx < statements size]]) ifFalse:
+ [s emitCCodeAsArgumentOn: aStream level: level + 1 generator: aCodeGen].
+ p2 := aStream position.
+ (idx < size and: [p2 > p1]) ifTrue:
- statements
- do:
- [:s |
- s emitCCommentOn: aStream level: level.
- s emitCCodeAsArgumentOn: aStream level: level + 1 generator: aCodeGen.
- statementWasComment := s isComment]
- separatedBy:
[((self endsWithCloseBracket: aStream)
+ or: [s isComment]) ifFalse: [aStream nextPut: $,].
+ aStream crtab: level]].
- or: [statementWasComment]) ifFalse: [aStream nextPut: $,].
- aStream crtab: level].
aStream nextPut: $)!
More information about the Vm-dev
mailing list