Skip to content

Commit

Permalink
Fixing remembering of objects when the target is a machine code refer…
Browse files Browse the repository at this point in the history
…ence
  • Loading branch information
PalumboN committed Jul 7, 2022
1 parent 398e73c commit b772b2f
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 36 deletions.
6 changes: 3 additions & 3 deletions smalltalksrc/VMMaker/CogARMv8Compiler.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ CogARMv8Compiler >> b: immediate26bitValue withLink: aBoolean [
self seeAlso: #bl:.

multiplier := immediate26bitValue / 4.
self assert: multiplier isInteger.
" self assert: multiplier isInteger."
twoComplement := multiplier > 0
ifTrue: [ multiplier ]
ifFalse: [ 2r11111111111111111111111111 - multiplier abs + 1 ].
Expand Down Expand Up @@ -779,7 +779,7 @@ CogARMv8Compiler >> branchCondition: condition offset: immediate19bitValue [
self assert: (16r3ffff allMask: immediate19bitValue abs >> 2).

multiplier := immediate19bitValue >> 2.
self assert: multiplier isInteger.
" self assert: multiplier isInteger."
twoComplement := multiplier < 0
ifTrue: [ 2r1111111111111111111 - multiplier abs + 1 ]
ifFalse: [ multiplier ].
Expand Down Expand Up @@ -4467,7 +4467,7 @@ CogARMv8Compiler >> ldrSize: is64Bits programCounterRelativeOffset: immediate19b

| twoComplement multiplier |
multiplier := immediate19bitValue / 4.
self assert: multiplier isInteger.
" self assert: multiplier isInteger."
twoComplement := multiplier > 0
ifTrue: [ multiplier ]
ifFalse: [ 2r1111111111111111111 - multiplier abs + 1 ].
Expand Down
7 changes: 5 additions & 2 deletions smalltalksrc/VMMaker/CogObjectRepresentation.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,14 @@ CogObjectRepresentation >> freeCounters: theCounters [
{ #category : #'compile abstract instructions' }
CogObjectRepresentation >> genCheckObjectPosition: destReg scratchReg: scratchReg valueReg: valueReg results: resultBlock [

| isDestYoung isOldAndOld isPermAndPerm recvIsPerm exit|
| isDestYoung isOldAndOld isPermAndPerm recvIsPerm exit valueIsMachineCode|

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

cogit CmpCq: objectMemory getMemoryMap newSpaceStart R: valueReg.
valueIsMachineCode := cogit JumpBelow: 0.

cogit CmpCq: objectMemory getMemoryMap fixedPermSpaceStart R: destReg.
recvIsPerm := cogit JumpAboveOrEqual: 0.
Expand All @@ -152,7 +155,7 @@ CogObjectRepresentation >> genCheckObjectPosition: destReg scratchReg: scratchRe

exit jmpTarget: (cogit Label).

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

Expand Down
19 changes: 13 additions & 6 deletions smalltalksrc/VMMaker/CogObjectRepresentationForSpur.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -2579,13 +2579,15 @@ CogObjectRepresentationForSpur >> genStoreCheckContextReceiverTrampoline [
CogObjectRepresentationForSpur >> genStoreCheckReceiverReg: destReg valueReg: valueReg scratchReg: scratchReg inFrame: inFrame [
"Generate the code for a store check of valueReg into destReg."

| jmpImmediate jmpDestYoung jmpOldAndOld jmpPermAndPerm jmpAlreadyRemembered|
| jmpImmediate jmpDestYoung jmpOldAndOld jmpPermAndPerm jmpAlreadyRemembered jmpIsMachineCode|

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


"Is value stored an immediate? If so we're done"
jmpImmediate := self genJumpImmediate: valueReg.
Expand All @@ -2594,9 +2596,10 @@ CogObjectRepresentationForSpur >> genStoreCheckReceiverReg: destReg valueReg: va
genCheckObjectPosition: destReg
scratchReg: scratchReg
valueReg: valueReg
results: [ :isDestYoung :isOldAndOld :isPermAndPerm |
results: [ :isDestYoung :isOldAndOld :isPermAndPerm :valueIsMachineCode |
jmpDestYoung := isDestYoung.
jmpOldAndOld := isOldAndOld.
jmpIsMachineCode := valueIsMachineCode.
jmpPermAndPerm := isPermAndPerm].


Expand All @@ -2610,9 +2613,10 @@ CogObjectRepresentationForSpur >> genStoreCheckReceiverReg: destReg valueReg: va
protectLinkRegIfNot: inFrame.
jmpImmediate jmpTarget:
(jmpDestYoung jmpTarget:
(jmpIsMachineCode jmpTarget:
(jmpOldAndOld jmpTarget:
(jmpPermAndPerm jmpTarget:
cogit Label))).
cogit Label)))).

CheckRememberedInTrampoline ifFalse:
[jmpAlreadyRemembered jmpTarget: jmpOldAndOld getJmpTarget].
Expand Down Expand Up @@ -2811,13 +2815,14 @@ 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 jmpOldAndOld jmpPermAndPerm jmpAlreadyRemembered |
| immutableJump jmpImmediate jmpDestYoung jmpOldAndOld jmpPermAndPerm jmpAlreadyRemembered jmpIsMachineCode|
<var: #immutableJump type: #'AbstractInstruction *'>
<var: #jmpImmediate type: #'AbstractInstruction *'>
<var: #jmpDestYoung type: #'AbstractInstruction *'>
<var: #jmpOldAndOld type: #'AbstractInstruction *'>
<var: #jmpPermAndPerm type: #'AbstractInstruction *'>
<var: #jmpAlreadyRemembered type: #'AbstractInstruction *'>
<var: #jmpIsMachineCode type: #'AbstractInstruction *'>

immutableJump := self genJumpImmutable: destReg scratchReg: scratchReg.

Expand All @@ -2835,9 +2840,10 @@ CogObjectRepresentationForSpur >> genStoreWithImmutabilityAndStoreCheckSourceReg
genCheckObjectPosition: destReg
scratchReg: scratchReg
valueReg: sourceReg
results: [ :isDestYoung :isOldAndOld :isPermAndPerm |
results: [ :isDestYoung :isOldAndOld :isPermAndPerm :valueIsMachineCode|
jmpDestYoung := isDestYoung.
jmpOldAndOld := isOldAndOld.
jmpIsMachineCode := valueIsMachineCode.
jmpPermAndPerm := isPermAndPerm].

"Need to remember this only if the remembered bit is not already set."
Expand All @@ -2854,8 +2860,9 @@ CogObjectRepresentationForSpur >> genStoreWithImmutabilityAndStoreCheckSourceReg
jmpImmediate jmpTarget:
(jmpDestYoung jmpTarget:
(jmpOldAndOld jmpTarget:
(jmpIsMachineCode jmpTarget:
(jmpPermAndPerm jmpTarget:
cogit Label))).
cogit Label)))).
CheckRememberedInTrampoline ifFalse:
[jmpAlreadyRemembered jmpTarget: jmpOldAndOld getJmpTarget].
^ 0
Expand Down
36 changes: 19 additions & 17 deletions smalltalksrc/VMMaker/Cogit.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -6838,26 +6838,29 @@ Cogit >> followForwardedLiteralsIn: cogMethod [
{ #category : #'garbage collection' }
Cogit >> followForwardedMethods [
<api>
<option: #SpurObjectMemory>
<var: #cogMethod type: #'CogMethod *'>
| cogMethod freedPIC |
<var: #cogMethod type: #'CogMethod *'>
| cogMethod freedPIC |
freedPIC := false.
cogMethod := self cCoerceSimple: methodZoneBase to: #'CogMethod *'.
[cogMethod < methodZone limitZony] whileTrue:
[cogMethod cmType = CMMethod ifTrue:
[(objectMemory isForwarded: cogMethod methodObject) ifTrue:
[cogMethod methodObject: (objectMemory followForwarded: cogMethod methodObject).
(objectMemory getMemoryMap isYoungObject: cogMethod methodObject) ifTrue:
[methodZone ensureInYoungReferrers: cogMethod]]].
cogMethod cmType = CMClosedPIC ifTrue:
[(self followMethodReferencesInClosedPIC: cogMethod) ifTrue:
[freedPIC := true.
methodZone freeMethod: cogMethod]].
cogMethod := methodZone methodAfter: cogMethod].
freedPIC ifTrue:
[self unlinkSendsToFree]
self enableCodeZoneWriteDuring: [
[ cogMethod < methodZone limitZony ] whileTrue: [
cogMethod cmType = CMMethod ifTrue: [
(objectMemory isForwarded: cogMethod methodObject) ifTrue: [
cogMethod methodObject:
(objectMemory followForwarded: cogMethod methodObject).
(objectMemory getMemoryMap isYoungObject: cogMethod methodObject)
ifTrue: [ methodZone ensureInYoungReferrers: cogMethod ] ] ].
cogMethod cmType = CMClosedPIC ifTrue: [
(self followMethodReferencesInClosedPIC: cogMethod) ifTrue: [
freedPIC := true.
methodZone freeMethod: cogMethod ] ].
cogMethod := methodZone methodAfter: cogMethod ].
freedPIC ifTrue: [ self unlinkSendsToFree ] ]
]
{ #category : #'garbage collection' }
Expand Down Expand Up @@ -7921,11 +7924,10 @@ Cogit >> generateClosedPICPrototype [
cPICEndSize := closedPICSize - (MaxCPICCases - 1 * cPICCaseSize + firstCPICCaseOffset).
closedPICSize := methodZone roundUpLength: closedPICSize.
self assert: picInterpretAbort address = (methodLabel address + self picInterpretAbortOffset).
self assert: (self expectedClosedPICPrototype: cPIC) = 0.
"tpr this is a little tiresome but after any assert checking we need to 0 out the case0 objRef rather than leaving 16r5EAF00D lying around"
self enableCodeZoneWriteDuring: [
self assert: (self expectedClosedPICPrototype: cPIC) = 0.
"tpr this is a little tiresome but after any assert checking we need to 0 out the case0 objRef rather than leaving 16r5EAF00D lying around"
backEnd storeLiteral: 0 beforeFollowingAddress: endCPICCase0 address - backEnd jumpLongByteSize].
"update the methodZoneBase so we keep the prototype around for later use"
Expand Down
31 changes: 24 additions & 7 deletions smalltalksrc/VMMaker/SpurMemoryManager.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -7202,6 +7202,12 @@ SpurMemoryManager >> isInNewSpace: objOop [
and: [self oop: objOop isGreaterThanOrEqualTo: memoryMap newSpaceStart]
]
{ #category : #'object testing' }
SpurMemoryManager >> isInObjectMemory: anOop [
^ anOop >= memoryMap startOfObjectMemory
]
{ #category : #'object testing' }
SpurMemoryManager >> isInOldSpace: address [
<api>
Expand Down Expand Up @@ -7471,14 +7477,22 @@ SpurMemoryManager >> isPermSpaceRememberedSetSane [
mustBeRemembered ifTrue: [
(self getFromPermSpaceRememberedSet isInRememberedSet: objOop)
ifFalse: [ self error: 'Object should be in remembered set'. ].
ifFalse: [
self logError: 'Offending Object: %p' _: objOop.
self error: 'Object should be in remembered set'. ].
(self isRemembered: objOop)
ifFalse: [ self error: 'Object should be marked as remembered' ]]
ifFalse: [
self logError: 'Offending Object: %p' _: objOop.
self error: 'Object should be marked as remembered' ]]
ifFalse: [
(self getFromPermSpaceRememberedSet isInRememberedSet: objOop)
ifTrue: [ self error: 'Object should not be in remembered set'. ].
ifTrue: [
self logError: 'Offending Object: %p' _: objOop.
self error: 'Object should not be in remembered set'. ].
(self isRemembered: objOop)
ifTrue: [ self error: 'Object should not be marked as remembered' ]
ifTrue: [
self logError: 'Offending Object: %p' _: objOop.
self error: 'Object should not be marked as remembered' ]
].
].
Expand Down Expand Up @@ -8823,9 +8837,9 @@ SpurMemoryManager >> moveToPermSpace: objOop [
"We check only if the object has not be already detected and only for the pointer slots."
((shouldBeRememberedInOldSpace not and: [ i <= numPointerSlots ])
and: [ (self isNonImmediate: referenced) and: [ (((memoryMap isOldObject: referenced)
or: [memoryMap isYoungObject: referenced])
and: [ (self isFixedKnownObject: referenced) not ]) ]])
and: [ (((self isFixedKnownObject: referenced) not
and: [ (self isNonImmediate: referenced) and: [ referenced >= self getMemoryMap newSpaceStart ]])
and: [(self getMemoryMap isYoungObject: referenced) or: [ self getMemoryMap isOldObject: referenced ]])])
ifTrue: [ shouldBeRememberedInOldSpace := true ].
self
Expand Down Expand Up @@ -9894,6 +9908,9 @@ SpurMemoryManager >> possiblePermObjectStoreInto: destObj value: valueObj [
(self isFixedKnownObject: valueObj)
ifTrue: [ ^ self ].
(self isInObjectMemory: valueObj)
ifFalse: [ ^ self ].
(self isPermanent: destObj) ifTrue: [
(self isPermanent: valueObj) ifFalse: [
(self isRemembered: destObj) ifFalse: [
Expand Down
2 changes: 1 addition & 1 deletion smalltalksrc/VMMaker/VMMemoryMap.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ VMMemoryMap >> isYoungObject: anOop [

<api>

^ (anOop bitAnd: spaceMaskToUse) = newSpaceMask
^ (anOop bitAnd: spaceMaskToUse) = newSpaceMask and: [ anOop >= newSpaceStart ]
]

{ #category : #accessing }
Expand Down
42 changes: 42 additions & 0 deletions smalltalksrc/VMMakerTests/VMPermanentSpaceMemoryTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,48 @@ VMPermanentSpaceMemoryTest >> setUp [
self createWeakArrayClass
]

{ #category : #'test - moving' }
VMPermanentSpaceMemoryTest >> testCompiledMethodWithMachineCodeIsNotRememberedWhenModified [

| oldObject1 permanentObject1 |

oldObject1 := self newOldSpaceObjectWithSlots: 2.

permanentObject1 := memory moveToPermSpace: oldObject1.

memory
storePointer: 0
ofObject: permanentObject1
withValue: (VMMemoryMapConfiguration forWordsize: wordSize) new codeZoneInitialAddress. "I create an address as it was a machine code method"

self deny: (memory isRemembered: permanentObject1).
self deny: (memory getFromOldSpaceRememberedSet isInRememberedSet:
permanentObject1).
self deny: (memory getFromPermSpaceRememberedSet isInRememberedSet:
permanentObject1)
]

{ #category : #'test - moving' }
VMPermanentSpaceMemoryTest >> testCompiledMethodWithMachineCodeIsNotRememberedWhenMoving [

| oldObject1 permanentObject1 |

oldObject1 := self newOldSpaceObjectWithSlots: 2.

memory
storePointer: 0
ofObject: oldObject1
withValue: (VMMemoryMapConfiguration forWordsize: wordSize) new codeZoneInitialAddress. "I create an address as it was a machine code method"

permanentObject1 := memory moveToPermSpace: oldObject1.

self deny: (memory isRemembered: permanentObject1).
self deny: (memory getFromOldSpaceRememberedSet isInRememberedSet:
permanentObject1).
self deny: (memory getFromPermSpaceRememberedSet isInRememberedSet:
permanentObject1)
]

{ #category : #'tests - allocation' }
VMPermanentSpaceMemoryTest >> testMarkingNewSpaceDoesNotMarkPermSpace [

Expand Down

0 comments on commit b772b2f

Please sign in to comment.