Skip to content

Commit

Permalink
- Adding second perm space
Browse files Browse the repository at this point in the history
- Adding tests
- Adding test in the JIT for detecting the position of objects
  • Loading branch information
tesonep committed Jun 17, 2022
1 parent 05b10cc commit 30a2533
Show file tree
Hide file tree
Showing 25 changed files with 649 additions and 395 deletions.
29 changes: 29 additions & 0 deletions smalltalksrc/VMMaker/CogObjectRepresentation.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,35 @@ CogObjectRepresentation >> freeCounters: theCounters [
self subclassResponsibility
]

{ #category : #'compile abstract instructions' }
CogObjectRepresentation >> genCheckObjectPosition: destReg scratchReg: scratchReg valueReg: valueReg results: resultBlock [

| isDestYoung isOldAndOld isPermAndPerm recvIsPerm exit|

<inline: true>
<var: #recvIsPerm type: #'AbstractInstruction *'>
<var: #exit type: #'AbstractInstruction *'>

cogit CmpCq: objectMemory getMemoryMap fixedPermSpaceStart R: destReg.
recvIsPerm := cogit JumpAboveOrEqual: 0.

cogit CmpCq: objectMemory getMemoryMap oldSpaceStart R: destReg.
isDestYoung := cogit JumpBelow: 0.

cogit CmpCq: objectMemory getMemoryMap oldSpaceStart R: valueReg.
isOldAndOld := cogit JumpAboveOrEqual: 0.
exit := cogit Jump: 0.

recvIsPerm jmpTarget: (cogit Label).
cogit CmpCq: objectMemory getMemoryMap fixedPermSpaceStart R: valueReg.
isPermAndPerm := cogit JumpAbove: 0.

exit jmpTarget: (cogit Label).

resultBlock value: isDestYoung value: isOldAndOld value: isPermAndPerm.
^ 0
]

{ #category : #'compile abstract instructions' }
CogObjectRepresentation >> genClearAndSetSmallIntegerTagsIn: scratchReg [
"Set the SmallInteger tag bits when the tag bits may be filled with garbage."
Expand Down
79 changes: 45 additions & 34 deletions smalltalksrc/VMMaker/CogObjectRepresentationForSpur.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -2578,23 +2578,29 @@ CogObjectRepresentationForSpur >> genStoreCheckContextReceiverTrampoline [
{ #category : #'compile abstract instructions' }
CogObjectRepresentationForSpur >> genStoreCheckReceiverReg: destReg valueReg: valueReg scratchReg: scratchReg inFrame: inFrame [
"Generate the code for a store check of valueReg into destReg."
| jmpImmediate jmpDestYoung jmpSourceOld jmpAlreadyRemembered |

| jmpImmediate jmpDestYoung jmpOldAndOld jmpPermAndPerm jmpAlreadyRemembered|

<var: #jmpImmediate type: #'AbstractInstruction *'>
<var: #jmpDestYoung type: #'AbstractInstruction *'>
<var: #jmpSourceOld type: #'AbstractInstruction *'>
<var: #jmpOldAndOld type: #'AbstractInstruction *'>
<var: #jmpPermAndPerm type: #'AbstractInstruction *'>
<var: #jmpAlreadyRemembered type: #'AbstractInstruction *'>

"Is value stored an immediate? If so we're done"
jmpImmediate := self genJumpImmediate: valueReg.
"Get the old/new boundary in scratchReg"
cogit MoveCw: objectMemory storeCheckBoundary R: scratchReg.
"Is target young? If so we're done"
cogit CmpR: scratchReg R: destReg. "N.B. FLAGS := destReg - scratchReg"
jmpDestYoung := cogit JumpBelow: 0.
"Is value stored old? If so we're done."
cogit CmpR: scratchReg R: valueReg. "N.B. FLAGS := valueReg - scratchReg"
jmpSourceOld := cogit JumpAboveOrEqual: 0.
"value is young and target is old.
Need to remember this only if the remembered bit is not already set."

self
genCheckObjectPosition: destReg
scratchReg: scratchReg
valueReg: valueReg
results: [ :isDestYoung :isOldAndOld :isPermAndPerm |
jmpDestYoung := isDestYoung.
jmpOldAndOld := isOldAndOld.
jmpPermAndPerm := isPermAndPerm].


"Need to remember this only if the remembered bit is not already set."
CheckRememberedInTrampoline ifFalse:
[jmpAlreadyRemembered := self genCheckRememberedBitOf: destReg scratch: scratchReg].
"Remembered bit is not set. Call store check to insert dest into remembered table."
Expand All @@ -2604,10 +2610,12 @@ CogObjectRepresentationForSpur >> genStoreCheckReceiverReg: destReg valueReg: va
protectLinkRegIfNot: inFrame.
jmpImmediate jmpTarget:
(jmpDestYoung jmpTarget:
(jmpSourceOld jmpTarget:
cogit Label)).
(jmpOldAndOld jmpTarget:
(jmpPermAndPerm jmpTarget:
cogit Label))).

CheckRememberedInTrampoline ifFalse:
[jmpAlreadyRemembered jmpTarget: jmpSourceOld getJmpTarget].
[jmpAlreadyRemembered jmpTarget: jmpOldAndOld getJmpTarget].
^0
]

Expand All @@ -2624,7 +2632,7 @@ CogObjectRepresentationForSpur >> genStoreCheckTrampoline [
cogit RetN: 0.
jumpSC jmpTarget: cogit Label].
^cogit
genTrampolineFor: #remember:
genTrampolineFor: #rememberObjInCorrectRememberedSet:
called: 'ceStoreCheckTrampoline'
numArgs: 1
arg: ReceiverResultReg
Expand Down Expand Up @@ -2704,7 +2712,7 @@ CogObjectRepresentationForSpur >> genStoreTrampolineCalled: trampolineName instV
<inline: false>
cogit zeroOpcodeIndex.
"SendNumArgsReg is mutated but we don't care as register are not live across the trampoline.
There is no reason why registers cannot be saved over the remember: call, but since the
There is no reason why registers cannot be saved over the rememberObjInCorrectRememberedSet: call, but since the
immutability check is a suspension point, registers cannot remain live."
jumpSC := self genJumpMutable: ReceiverResultReg scratchReg: SendNumArgsReg.
cogit
Expand Down Expand Up @@ -2735,7 +2743,7 @@ CogObjectRepresentationForSpur >> genStoreTrampolineCalled: trampolineName instV
jumpRC opcode: JumpZero.
cogit RetN: 0].
jumpRC jmpTarget: cogit Label].
^ cogit genTrampolineFor: #remember:
^ cogit genTrampolineFor: #rememberObjInCorrectRememberedSet:
called: trampolineName
numArgs: 1
arg: ReceiverResultReg
Expand Down Expand Up @@ -2803,11 +2811,12 @@ CogObjectRepresentationForSpur >> genStoreValue: value instance: destReg numSlot
CogObjectRepresentationForSpur >> genStoreWithImmutabilityAndStoreCheckSourceReg: sourceReg slotIndex: index destReg: destReg scratchReg: scratchReg needRestoreRcvr: needRestoreRcvr [
"Store check code is duplicated to use a single trampoline"
<option: #IMMUTABILITY>
| immutableJump jmpImmediate jmpDestYoung jmpSourceOld jmpAlreadyRemembered |
| immutableJump jmpImmediate jmpDestYoung jmpOldAndOld jmpPermAndPerm jmpAlreadyRemembered |
<var: #immutableJump type: #'AbstractInstruction *'>
<var: #jmpImmediate type: #'AbstractInstruction *'>
<var: #jmpDestYoung type: #'AbstractInstruction *'>
<var: #jmpSourceOld type: #'AbstractInstruction *'>
<var: #jmpOldAndOld type: #'AbstractInstruction *'>
<var: #jmpPermAndPerm type: #'AbstractInstruction *'>
<var: #jmpAlreadyRemembered type: #'AbstractInstruction *'>

immutableJump := self genJumpImmutable: destReg scratchReg: scratchReg.
Expand All @@ -2818,19 +2827,20 @@ CogObjectRepresentationForSpur >> genStoreWithImmutabilityAndStoreCheckSourceReg
cogit MoveR: sourceReg
Mw: index * objectMemory wordSize + objectMemory baseHeaderSize
r: destReg.

"store check"
jmpImmediate := self genJumpImmediate: sourceReg.
"Get the old/new boundary in scratchReg"
cogit MoveCw: objectMemory storeCheckBoundary R: scratchReg.
"Is target young? If so we're done"
cogit CmpR: scratchReg R: destReg. "N.B. FLAGS := destReg - scratchReg"
jmpDestYoung := cogit JumpBelow: 0.
"Is value stored old? If so we're done."
cogit CmpR: scratchReg R: sourceReg. "N.B. FLAGS := valueReg - scratchReg"
jmpSourceOld := cogit JumpAboveOrEqual: 0.
"value is young and target is old.
Need to remember this only if the remembered bit is not already set."

self
genCheckObjectPosition: destReg
scratchReg: scratchReg
valueReg: sourceReg
results: [ :isDestYoung :isOldAndOld :isPermAndPerm |
jmpDestYoung := isDestYoung.
jmpOldAndOld := isOldAndOld.
jmpPermAndPerm := isPermAndPerm].

"Need to remember this only if the remembered bit is not already set."
CheckRememberedInTrampoline ifFalse:
[jmpAlreadyRemembered := self genCheckRememberedBitOf: destReg scratch: scratchReg].
"Set the inst var index for the benefit of the immutability check. The trampoline will
Expand All @@ -2843,10 +2853,11 @@ CogObjectRepresentationForSpur >> genStoreWithImmutabilityAndStoreCheckSourceReg

jmpImmediate jmpTarget:
(jmpDestYoung jmpTarget:
(jmpSourceOld jmpTarget:
cogit Label)).
(jmpOldAndOld jmpTarget:
(jmpPermAndPerm jmpTarget:
cogit Label))).
CheckRememberedInTrampoline ifFalse:
[jmpAlreadyRemembered jmpTarget: jmpSourceOld getJmpTarget].
[jmpAlreadyRemembered jmpTarget: jmpOldAndOld getJmpTarget].
^ 0
]

Expand Down
1 change: 1 addition & 0 deletions smalltalksrc/VMMaker/Cogit.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -4024,6 +4024,7 @@ Cogit >> ceCaptureCStackPointers [
{ #category : #testing }
Cogit >> ceCheckFeatures [
<cmacro: '() ceCheckFeaturesFunction()'>
^self simulateLeafCallOf: ceCheckFeaturesFunction
]
Expand Down
2 changes: 1 addition & 1 deletion smalltalksrc/VMMaker/InterpreterPrimitives.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -4138,7 +4138,7 @@ InterpreterPrimitives >> primitiveSpurStringReplace [
[mustRemember := true].
objectMemory storePointerUnchecked: i ofObject: array withValue: oop].
mustRemember ifTrue:
[objectMemory possibleRootStoreInto: array]]
[objectMemory possibleOldObjectStoreInto: array]]
ifFalse:
[start - 1 to: stop - 1 do:
[:i | objectMemory storePointerUnchecked: i ofObject: array withValue: (objectMemory fetchPointer: srcDelta + i ofObject: repl)]]]
Expand Down
6 changes: 0 additions & 6 deletions smalltalksrc/VMMaker/Spur32BitCoMemoryManager.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,6 @@ Spur32BitCoMemoryManager >> receiverTagBitsForMethod: aMethodObj [
self characterTag]
]

{ #category : #'cog jit support' }
Spur32BitCoMemoryManager >> remember: objOop [
<doNotGenerate>
^scavenger remember: objOop
]

{ #category : #'trampoline support' }
Spur32BitCoMemoryManager >> scavengeThresholdAddress [
<api>
Expand Down
2 changes: 1 addition & 1 deletion smalltalksrc/VMMaker/Spur32BitMemoryManager.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ Spur32BitMemoryManager >> shorten: objOop toIndexableSize: indexableSize [
ofObject: copy
withValue: (self fetchPointer: i ofObject: objOop)].
(self isRemembered: objOop) ifTrue:
[scavenger remember: copy].
[fromOldSpaceRememberedSet doRemember: copy].
self forward: objOop to: copy.
^0].

Expand Down
6 changes: 0 additions & 6 deletions smalltalksrc/VMMaker/Spur64BitCoMemoryManager.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,6 @@ Spur64BitCoMemoryManager >> receiverTagBitsForMethod: aMethodObj [
^self smallFloatTag
]

{ #category : #'cog jit support' }
Spur64BitCoMemoryManager >> remember: objOop [
<doNotGenerate>
^scavenger remember: objOop
]

{ #category : #'trampoline support' }
Spur64BitCoMemoryManager >> scavengeThresholdAddress [
<api>
Expand Down
2 changes: 1 addition & 1 deletion smalltalksrc/VMMaker/Spur64BitMemoryManager.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ Spur64BitMemoryManager >> shorten: objOop toIndexableSize: indexableSize [
ofObject: copy
withValue: (self fetchPointer: i ofObject: objOop)].
(self isRemembered: objOop) ifTrue:
[scavenger remember: copy].
[fromOldSpaceRememberedSet doRemember: copy].
self forward: objOop to: copy.
^0].

Expand Down

0 comments on commit 30a2533

Please sign in to comment.