Skip to content

Commit aede3fc

Browse files
authored
Merge pull request OpenSmalltalk#565 from guillep/fix/ephemeron-immediate-keys
Verify ephemeron key is not immediate when marking
2 parents bcef61a + a48ce2b commit aede3fc

File tree

2 files changed

+62
-37
lines changed

2 files changed

+62
-37
lines changed

smalltalksrc/VMMaker/SpurMemoryManager.class.st

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8315,7 +8315,6 @@ SpurMemoryManager >> markInactiveEphemerons [
83158315

83168316
{ #category : #'gc - global' }
83178317
SpurMemoryManager >> markLoopFrom: objOop [
8318-
83198318
"Scan objOop and all objects on the mark stack, until the mark stack is empty.
83208319
N.B. When the incremental GC is written this will probably be refactored as
83218320
markLoopFrom: objOop while: aBlock"
@@ -8326,61 +8325,66 @@ SpurMemoryManager >> markLoopFrom: objOop [
83268325
objToScan := objOop.
83278326
"To avoid overflowing the mark stack when we encounter large objects, we
83288327
push the obj, then its numStrongSlots, and then index the object from the stack."
8329-
[
8328+
[
83308329
(self isImmediate: objToScan)
83318330
ifTrue: [ scanLargeObject := true ]
83328331
ifFalse: [
8333-
numStrongSlots := ((self isEphemeron: objToScan) and: [ self isMarked: (self keyOfEphemeron: objToScan) ])
8334-
ifTrue: [ self numSlotsOf: objToScan ]
8335-
ifFalse: [ self numStrongSlotsOfInephemeral: objToScan ].
8332+
numStrongSlots := ((self isEphemeron: objToScan) and: [
8333+
| key |
8334+
(self isImmediate:
8335+
(key := self keyOfEphemeron: objToScan)) or: [
8336+
self isMarked: key ] ])
8337+
ifTrue: [ self numSlotsOf: objToScan ]
8338+
ifFalse: [
8339+
self numStrongSlotsOfInephemeral: objToScan ].
83368340
scanLargeObject := numStrongSlots > self traceImmediatelySlotLimit ].
83378341
scanLargeObject
83388342
ifTrue: [ "scanning a large object. scan until hitting an unmarked object, then switch to it, if any."
83398343
(self isImmediate: objToScan)
8340-
ifTrue: [
8344+
ifTrue: [
83418345
index := self integerValueOf: objToScan.
83428346
objToScan := self topOfObjStack: markStack ]
8343-
ifFalse: [
8347+
ifFalse: [
83448348
index := numStrongSlots.
83458349
self markAndTraceClassOf: objToScan ].
8346-
[ index > 0 ] whileTrue: [
8350+
[ index > 0 ] whileTrue: [
83478351
index := index - 1.
83488352
field := self fetchPointer: index ofObject: objToScan.
8349-
(self isNonImmediate: field) ifTrue: [
8353+
(self isNonImmediate: field) ifTrue: [
83508354
(self isForwarded: field) ifTrue: [ "fixFollowedField: is /not/ inlined"
83518355
field := self
83528356
fixFollowedField: index
83538357
ofObject: objToScan
83548358
withInitialValue: field ].
8355-
(self markAndShouldScan: field) ifTrue: [
8356-
index > 0 ifTrue: [
8357-
(self topOfObjStack: markStack) ~= objToScan ifTrue: [
8359+
(self markAndShouldScan: field) ifTrue: [
8360+
index > 0 ifTrue: [
8361+
(self topOfObjStack: markStack) ~= objToScan ifTrue: [
83588362
self push: objToScan onObjStack: markStack ].
83598363
self push: (self integerObjectOf: index) onObjStack: markStack ].
83608364
objToScan := field.
83618365
index := -1 ] ] ].
83628366
index >= 0 ifTrue: [ "if loop terminated without finding an unmarked referent, switch to top of stack."
83638367
objToScan := self popObjStack: markStack.
8364-
objToScan = objOop ifTrue: [
8368+
objToScan = objOop ifTrue: [
83658369
objToScan := self popObjStack: markStack ] ] ]
83668370
ifFalse: [ "scanning a small object. scan, marking, pushing unmarked referents, then switch to the top of the stack."
83678371
index := numStrongSlots.
83688372
self markAndTraceClassOf: objToScan.
8369-
[ index > 0 ] whileTrue: [
8373+
[ index > 0 ] whileTrue: [
83708374
index := index - 1.
83718375
field := self fetchPointer: index ofObject: objToScan.
8372-
(self isNonImmediate: field) ifTrue: [
8376+
(self isNonImmediate: field) ifTrue: [
83738377
(self isForwarded: field) ifTrue: [ "fixFollowedField: is /not/ inlined"
83748378
field := self
83758379
fixFollowedField: index
83768380
ofObject: objToScan
83778381
withInitialValue: field ].
8378-
(self markAndShouldScan: field) ifTrue: [
8382+
(self markAndShouldScan: field) ifTrue: [
83798383
self push: field onObjStack: markStack.
8380-
((self rawNumSlotsOf: field) > self traceImmediatelySlotLimit
8381-
and: [
8384+
((self rawNumSlotsOf: field) > self traceImmediatelySlotLimit
8385+
and: [
83828386
(numStrongSlots := self numStrongSlotsOfInephemeral: field)
8383-
> self traceImmediatelySlotLimit ]) ifTrue: [
8387+
> self traceImmediatelySlotLimit ]) ifTrue: [
83848388
self
83858389
push: (self integerObjectOf: numStrongSlots)
83868390
onObjStack: markStack ] ] ] ].
@@ -9252,30 +9256,33 @@ SpurMemoryManager >> numStrongSlotsOfInephemeral: objOop [
92529256
"Answer the number of strong pointer fields in the given object,
92539257
which is expected not to be an active ephemeron.
92549258
Works with CompiledMethods, as well as ordinary objects."
9259+
92559260
<inline: true>
9256-
| fmt numSlots contextSize numLiterals header |
9261+
| fmt numSlots contextSize numLiterals header |
92579262
fmt := self formatOf: objOop.
9258-
self assert: (fmt ~= self ephemeronFormat or: [self isMarked: (self keyOfEphemeron: objOop)]).
9259-
fmt <= self lastPointerFormat ifTrue:
9260-
[numSlots := self numSlotsOf: objOop.
9261-
fmt <= self arrayFormat ifTrue:
9262-
[^numSlots].
9263-
fmt = self indexablePointersFormat ifTrue:
9264-
[(self isContextNonImm: objOop) ifTrue:
9265-
[coInterpreter setTraceFlagOnContextsFramesPageIfNeeded: objOop.
9266-
"contexts end at the stack pointer"
9267-
contextSize := coInterpreter fetchStackPointerOf: objOop.
9268-
^CtxtTempFrameStart + contextSize].
9269-
^numSlots].
9270-
fmt = self weakArrayFormat ifTrue:
9271-
[^self fixedFieldsOfClass: (self fetchClassOfNonImm: objOop)]].
9272-
fmt = self forwardedFormat ifTrue: [^1].
9273-
fmt < self firstCompiledMethodFormat ifTrue: [^0]. "no pointers"
9263+
self assert: (fmt ~= self ephemeronFormat or: [
9264+
| key |
9265+
(self isImmediate: (key := self keyOfEphemeron: objOop)) or: [
9266+
self isMarked: key ] ]).
9267+
fmt <= self lastPointerFormat ifTrue: [
9268+
numSlots := self numSlotsOf: objOop.
9269+
fmt <= self arrayFormat ifTrue: [ ^ numSlots ].
9270+
fmt = self indexablePointersFormat ifTrue: [
9271+
(self isContextNonImm: objOop) ifTrue: [
9272+
coInterpreter setTraceFlagOnContextsFramesPageIfNeeded: objOop.
9273+
"contexts end at the stack pointer"
9274+
contextSize := coInterpreter fetchStackPointerOf: objOop.
9275+
^ CtxtTempFrameStart + contextSize ].
9276+
^ numSlots ].
9277+
fmt = self weakArrayFormat ifTrue: [
9278+
^ self fixedFieldsOfClass: (self fetchClassOfNonImm: objOop) ] ].
9279+
fmt = self forwardedFormat ifTrue: [ ^ 1 ].
9280+
fmt < self firstCompiledMethodFormat ifTrue: [ ^ 0 ]. "no pointers"
92749281

92759282
"CompiledMethod: contains both pointers and bytes"
92769283
header := self methodHeaderOf: objOop.
92779284
numLiterals := self literalCountOfMethodHeader: header.
9278-
^numLiterals + LiteralStart
9285+
^ numLiterals + LiteralStart
92799286
]
92809287

92819288
{ #category : #'object access' }

smalltalksrc/VMMakerTests/VMSpurOldSpaceGarbageCollectorTest.class.st

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,24 @@ VMSpurOldSpaceGarbageCollectorTest >> testEphemeronOverflowUnscannedEphemeronQue
416416
equals: numberJustOverLimit
417417
]
418418

419+
{ #category : #tests }
420+
VMSpurOldSpaceGarbageCollectorTest >> testEphemeronWithImmediateKeyShouldNotFail [
421+
422+
| ephemeron1 key |
423+
ephemeron1 := self newEphemeronObjectWithSlots: 5.
424+
self keepObjectInVMVariable1: ephemeron1.
425+
key := memory integerObjectOf: 15.
426+
memory storePointer: 0 ofObject: ephemeron1 withValue: key.
427+
428+
memory setCheckForLeaks: 63. "all"
429+
memory fullGC.
430+
431+
self
432+
assert:
433+
(memory fetchInteger: 0 ofObject: self keptObjectInVMVariable1)
434+
equals: 15
435+
]
436+
419437
{ #category : #tests }
420438
VMSpurOldSpaceGarbageCollectorTest >> testGrowOldSpace [
421439

0 commit comments

Comments
 (0)