Skip to content

SpurMemoryManager>>#enterIntoClassTable: skips potentially free entries #759

@Sabine-Schnabeltier

Description

@Sabine-Schnabeltier

When searching for a free entry to use for a new Class, minorIndex should be set to zero after searching the first page. Otherwise, only entries between the initial minorIndex and the end of each subsequent page are searched. Also, when incrementing majorIndex, the wrap mask should be self classTableRootSlots - 1 and not self classIndexMask (see below **).

I think the missing reset of minorIndex has led to holes in the class table for the currently released Squeak and Cuis images. (Cuis has fewer than 2000 classes in the image but the table has them spread over around 20 sparsely populated pages (~20000 entries)).

enterIntoClassTable: aBehavior
	"Enter aBehavior into the class table and answer 0.  Otherwise answer a primitive failure code."
	<inline: false>
	| initialMajorIndex majorIndex minorIndex page |
	majorIndex := classTableIndex >> self classTableMajorIndexShift.
	initialMajorIndex := majorIndex.
	"classTableIndex should never index the first page; it's reserved for known classes"
	self assert: initialMajorIndex > 0.
	minorIndex := classTableIndex bitAnd: self classTableMinorIndexMask.

	[page := self fetchPointer: majorIndex ofObject: hiddenRootsObj.
	 page = nilObj ifTrue:
		[page := self allocateSlotsInOldSpace: self classTablePageSize
					format: self arrayFormat
					classIndex: self arrayClassIndexPun.
		 page ifNil:
			[^PrimErrNoMemory halt].
		 self fillObj: page numSlots: self classTablePageSize with: nilObj.
		 self storePointer: majorIndex
			ofObject: hiddenRootsObj
			withValue: page.
		 numClassTablePages := numClassTablePages + 1.
		 minorIndex := 0].
	 minorIndex to: self classTablePageSize - 1 do:
		[:i|
		(self fetchPointer: i ofObject: page) = nilObj ifTrue:
			[classTableIndex := majorIndex << self classTableMajorIndexShift + i.
			 "classTableIndex must never index the first page, which is reserved for classes known to the VM."
			 self assert: classTableIndex >= (1 << self classTableMajorIndexShift).
			 self storePointer: i
				ofObject: page
				withValue: aBehavior.
			 self setHashBitsOf: aBehavior to: classTableIndex.
			 self assert: (self classAtIndex: (self rawHashBitsOf: aBehavior)) = aBehavior.
			 ^0]].
	"**  Missing: minorIndex := 0.  **"
	"**  classIndexMask is 22 bits; instead the following should be using (self classTableRootSlots - 1)  **"
	 majorIndex := (majorIndex + 1 bitAnd: self classIndexMask) max: 1.
	 majorIndex = initialMajorIndex ifTrue: "wrapped; table full"
		[^PrimErrLimitExceeded]] repeat

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions