[Vm-dev] VM Maker: VMMaker.oscog-cb.2413.mcz

commits at source.squeak.org commits at source.squeak.org
Mon Jun 11 08:09:10 UTC 2018


ClementBera uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-cb.2413.mcz

==================== Summary ====================

Name: VMMaker.oscog-cb.2413
Author: cb
Time: 11 June 2018, 10:08:32.760001 am
UUID: c1f5cce4-832d-4512-bf43-1d69f1a3abc2
Ancestors: VMMaker.oscog-cb.2412

Fixed a bug when new segment was allocated in C sometimes the swizzle field used by SelectiveCompactor got corrupted. Changed assertions here and there.

Now SelectiveCompactor starts to resist serious stress benchmarks... I need to try again the 20+Gb bench and it's good to go.

=============== Diff against VMMaker.oscog-cb.2412 ===============

Item was changed:
  ----- Method: Spur32BitMMLECoSimulator>>fetchPointer:ofObject: (in category 'object access') -----
  fetchPointer: fieldIndex ofObject: objOop
  	self assert: (self isForwarded: objOop) not.
  	self assert: (fieldIndex >= 0 and: [fieldIndex < (self numSlotsOfAny: objOop)
+ 				or: [fieldIndex = 0 "forwarders"]]).
- 				or: [fieldIndex = 0 "forwarders and free objs"
- 				or: [fieldIndex = 1 and: [self isFreeObject: objOop]]]]).
  	^super fetchPointer: fieldIndex ofObject: objOop!

Item was changed:
  ----- Method: Spur32BitMMLESimulator>>fetchPointer:ofObject: (in category 'object access') -----
  fetchPointer: fieldIndex ofObject: objOop
  	self assert: (self isForwarded: objOop) not.
  	self assert: (fieldIndex >= 0 and: [fieldIndex < (self numSlotsOfAny: objOop)
+ 				or: [fieldIndex = 0 "forwarders"]]).
- 				or: [fieldIndex = 0 "forwarders and free objs"
- 				or: [fieldIndex = 1 and: [self isFreeObject: objOop]]]]).
  	^super fetchPointer: fieldIndex ofObject: objOop!

Item was changed:
  ----- Method: Spur64BitMMLECoSimulator>>fetchPointer:ofObject: (in category 'object access') -----
  fetchPointer: fieldIndex ofObject: objOop
  	self assert: (self isForwarded: objOop) not.
  	self assert: (fieldIndex >= 0 and: [fieldIndex < (self numSlotsOfAny: objOop)
+ 				or: [fieldIndex = 0 "forwarders"]]).
- 				or: [fieldIndex = 0 "forwarders and free objs"]]).
  	^super fetchPointer: fieldIndex ofObject: objOop!

Item was changed:
  ----- Method: Spur64BitMMLESimulator>>fetchPointer:ofObject: (in category 'object access') -----
  fetchPointer: fieldIndex ofObject: objOop
  	self assert: (self isForwarded: objOop) not.
  	self assert: (fieldIndex >= 0 and: [fieldIndex < (self numSlotsOfAny: objOop)
+ 				or: [fieldIndex = 0 "forwarders"]]).
- 				or: [fieldIndex = 0 "forwarders and free objs"]]).
  	^super fetchPointer: fieldIndex ofObject: objOop!

Item was changed:
  ----- Method: SpurMemoryManager>>addToFreeList:bytes: (in category 'free space') -----
  addToFreeList: freeChunk bytes: chunkBytes
  	"Add freeChunk to the relevant freeList.
  	 For the benefit of sortedFreeObject:, if freeChunk is large, answer the treeNode it
  	 is added to, if it is added to the next list of a freeTreeNode, otherwise answer 0."
  	| index |
  	"coInterpreter transcript ensureCr. coInterpreter print: 'freeing '. self printFreeChunk: freeChunk."
  	self assert: (self isFreeObject: freeChunk).
  	self assert: chunkBytes = (self bytesInObject: freeChunk).
+ 	"Too slow to be enabled byt default but useful to debug Selective...
+ 	 self deny: (compactor isSegmentBeingCompacted: (segmentManager segmentContainingObj: freeChunk))."
  	index := chunkBytes / self allocationUnit.
  	index < self numFreeLists ifTrue:
  		[self setNextFreeChunkOf: freeChunk withValue: (freeLists at: index) chunkBytes: chunkBytes.
  		(self bytesBigEnoughForPrevPointer: chunkBytes) ifTrue:
  			[self storePointer: self freeChunkPrevIndex ofFreeChunk: freeChunk withValue: 0].
  		 freeLists at: index put: freeChunk.
  		 freeListsMask := freeListsMask bitOr: 1 << index.
  		 ^0].
  
  	^self addToFreeTree: freeChunk bytes: chunkBytes!

Item was added:
+ ----- Method: SpurMemoryManager>>assertFreeChunkPrevHeadZero (in category 'free space') -----
+ assertFreeChunkPrevHeadZero
+ 	|min|
+ 	self wordSize = 8 ifTrue: [min := 3] ifFalse: [min := 2].
+ 	min to: self numFreeLists - 1 do:
+ 		[:i| 
+ 		 	(freeLists at: i) ~= 0 ifTrue:
+ 				[self assert: (self bytesBigEnoughForPrevPointer: (freeLists at: i)).
+ 				 self assert: (self fetchPointer: self freeChunkPrevIndex ofFreeChunk: (freeLists at: i)) = 0]].
+ 	"Large chunks"
+ 	self freeTreeNodesDo: [:freeNode |
+ 		self assert: (self fetchPointer: self freeChunkPrevIndex ofFreeChunk: freeNode) = 0.
+ 		freeNode].
+ 	^ true!

Item was changed:
  ----- Method: SpurMemoryManager>>assertInnerValidFreeObject: (in category 'free space') -----
  assertInnerValidFreeObject: objOop
+ 	<inline: #never> "we don't want to inline so we can nest that in an assertion with the return true so the production VM does not generate any code here, while in simulation, the code breaks on the assertion we want to."
- 	<inline: #never> "we don't want to inline so we can nest that in an assertion with the return true so the production VM does not generate any code here, whil ein simulation, the code breaks on the assertion we want to."
  	| chunk index |
- 	"duplicated assertions from isValidFreeObject: because I need to know what is wrong not only that it is not valid (I got bored of stepping inside isValidFreeObject:...)"
  	self assert: (self oop: (self addressAfter: objOop) isLessThanOrEqualTo: endOfMemory).
  	chunk := self fetchPointer: self freeChunkNextIndex ofFreeChunk: objOop.
  	self assert: (chunk = 0 or: [self isFreeOop: chunk]).
  	(self bytesBigEnoughForPrevPointer: (self bytesInObject: objOop)) ifTrue:
  		["double linkedlist assertions"
  		 chunk := self fetchPointer: self freeChunkNextIndex ofFreeChunk: objOop.
  		 chunk = 0 ifFalse: 
  			[self assert: (self isFreeOop: chunk).
  			 self assert: objOop = (self fetchPointer: self freeChunkPrevIndex ofFreeChunk: chunk)].
  		chunk := self fetchPointer: self freeChunkPrevIndex ofFreeChunk: objOop.
  		index := (self bytesInObject: objOop) / self allocationUnit.
+ 		(index < self numFreeLists and: [1 << index <= freeListsMask]) 
+ 			ifTrue: 
+ 				[(freeLists at: index) = objOop ifTrue: [self assert: chunk = 0]]
+ 			ifFalse: 
+ 				[self freeTreeNodesDo: [:freeNode |
+ 					freeNode = objOop ifTrue: [self assert: chunk = 0]. freeNode]].
- 		(index < self numFreeLists and: [1 << index <= freeListsMask]) ifTrue: 
- 			[(freeLists at: index) = objOop ifTrue: [self assert: chunk = 0]].
  		 chunk = 0 ifFalse: 
  			[self assert: (self isFreeOop: chunk).
  			 self assert: objOop = (self fetchPointer: self freeChunkNextIndex ofFreeChunk: chunk)]].
  	(self isLargeFreeObject: objOop) ifTrue: 
  		["Tree assertions"
  		chunk := self fetchPointer: self freeChunkParentIndex ofFreeChunk: objOop.
  		self assert: (chunk = 0 or: [(self isFreeOop: chunk) and: [self isLargeFreeObject: chunk]]).
  		chunk := self fetchPointer: self freeChunkSmallerIndex ofFreeChunk: objOop.
  		self assert: (chunk = 0 or: [(self isFreeOop: chunk) and: [self isLargeFreeObject: chunk]]).
  		chunk := self fetchPointer: self freeChunkLargerIndex ofFreeChunk: objOop.
  		self assert: (chunk = 0 or: [(self isFreeOop: chunk) and: [self isLargeFreeObject: chunk]])].
  	^ true!

Item was changed:
  ----- Method: SpurMemoryManager>>fetchPointer:ofFreeChunk: (in category 'heap management') -----
  fetchPointer: fieldIndex ofFreeChunk: objOop
- 	self assert: (fieldIndex >= 0 and: [fieldIndex < (self numSlotsOfAny: objOop)
- 				or: [fieldIndex = 0 "forwarders and free objs"
- 				or: [fieldIndex = 1 and: [self wordSize = 4]]]]).
  	^self longAt: objOop + self baseHeaderSize + (fieldIndex << self shiftForWord)!

Item was changed:
  ----- Method: SpurMemoryManager>>printFreeChunk:printAsTreeNode: (in category 'debug printing') -----
  printFreeChunk: freeChunk printAsTreeNode: printAsTreeNode
  	| numBytes |
  	numBytes := self bytesInObject: freeChunk.
  	coInterpreter
  		print: 'freeChunk '; printHexPtrnp: freeChunk.
  	printAsTreeNode ifTrue:
  		[coInterpreter print: ' - '; printHexPtrnp:(self addressAfter: freeChunk)].
  	coInterpreter
  		print: ' bytes '; printNum: numBytes;
  		print: ' next '; printHexPtrnp: (self fetchPointer: self freeChunkNextIndex
  											ofFreeChunk: freeChunk).
+ 	(self bytesBigEnoughForPrevPointer: numBytes) ifTrue: 
+ 		[coInterpreter
+ 			print: ' prev '; printHexPtrnp: (self fetchPointer: self freeChunkPrevIndex
+ 											ofFreeChunk: freeChunk).].
  	(numBytes >= (self numFreeLists * self allocationUnit)
  	 and: [printAsTreeNode]) ifTrue:
  		[coInterpreter
  			print: ' ^ '; printHexPtrnp: (self fetchPointer: self freeChunkParentIndex
  											ofFreeChunk: freeChunk);
  			print: ' < '; printHexPtrnp: (self fetchPointer: self freeChunkSmallerIndex
  											ofFreeChunk: freeChunk);
  			print: ' > '; printHexPtrnp: (self fetchPointer: self freeChunkLargerIndex
  											ofFreeChunk: freeChunk)].
  	coInterpreter cr!

Item was changed:
  ----- Method: SpurMemoryManager>>storePointer:ofFreeChunk:withValue: (in category 'heap management') -----
  storePointer: fieldIndex ofFreeChunk: objOop withValue: valuePointer
  
  	self assert: (self isFreeObject: objOop).
+ 	self assert: (valuePointer = 0 or: [self isFreeObject: valuePointer]).		
- 	self assert: (valuePointer = 0 or: [self isFreeObject: valuePointer]).
- 	self assert: (fieldIndex >= 0 and: [fieldIndex < (self numSlotsOfAny: objOop)
- 				or: [fieldIndex = 0 "forwarders and free objs"
- 				or: [fieldIndex = 1 and: [self wordSize = 4]]]]).
- 			
  	^self
  		longAt: objOop + self baseHeaderSize + (fieldIndex << self shiftForWord)
  		put: valuePointer!

Item was changed:
  ----- Method: SpurMemoryManager>>updateFreeLists (in category 'initialization') -----
  updateFreeLists
  	"Snapshot did not guarantee the state of the freelist prevLink, so we need to update it.
  	 Effectively transforms the freechunk single linked list in double linked list."
  	|min|
  	"Small chunks"
  	"Skip in 64 bits size 1 which is single linked list - pathological case"
+ 	self wordSize = 8 ifTrue: [min := 3] ifFalse: [min := 2].
- 	self wordSize = 8 ifTrue: [min := 2] ifFalse: [min := 1].
  	min to: self numFreeLists - 1 do:
  		[:i| self updateListStartingAt: (freeLists at: i)].
  	"Large chunks"
  	self freeTreeNodesDo: [:freeNode |
  		self updateListStartingAt: freeNode.
  		freeNode]!

Item was changed:
  ----- Method: SpurSegmentManager>>addSegmentOfSize: (in category 'growing/shrinking memory') -----
  addSegmentOfSize: ammount
  	<returnTypeC: #'SpurSegmentInfo *'>
  	<inline: false>
  	| allocatedSize |
  	<var: #newSeg type: #'SpurSegmentInfo *'>
  	<var: #segAddress type: #'void *'>
  	<var: #allocatedSize type: #'usqInt'>
  	self cCode: [] inSmalltalk: [segments ifNil: [^nil]]. "bootstrap"
  	(manager "sent to the manager so that the simulator can increase memory to simulate a new segment"
  			sqAllocateMemorySegmentOfSize: ammount
  			Above: (self firstGapOfSizeAtLeast: ammount)
  			AllocatedSizeInto: (self cCode: [self addressOf: allocatedSize]
  									inSmalltalk: [[:sz| allocatedSize := sz]])) ifNotNil:
  		[:segAddress| | newSegIndex newSeg |
  		 newSegIndex := self insertSegmentFor: segAddress asUnsignedIntegerPtr.
  		 "Simulation insertion code duplicates entries if newSegIndex ~= numSegments - 1"
  		 self cCode: '' inSmalltalk: [segments at: newSegIndex put: SpurSegmentInfo new].
  		 newSeg := self addressOf: (segments at: newSegIndex).
  		 newSeg
  			segStart: segAddress asUnsignedIntegerPtr;
+ 			segSize: allocatedSize;
+ 			swizzle: 0. "Required in the C version only"
- 			segSize: allocatedSize.
  		 self assert: self segmentOverlap not. "self printSegmentAddresses."
  		 self bridgeFrom: (self addressOf: (segments at: newSegIndex - 1)) to: newSeg.
  		 self bridgeFrom: newSeg to: (newSegIndex = (numSegments - 1) ifFalse:
  										[self addressOf: (segments at: newSegIndex + 1)]).
  		 totalHeapSizeIncludingBridges := totalHeapSizeIncludingBridges + allocatedSize.
  		 "test isInMemory:"
  		 0 to: numSegments - 1 do:
  			[:i|
  			self assert: (self isInSegments: (segments at: i) segStart).
  			self assert: (self isInSegments: (segments at: i) segLimit - manager wordSize).
  			self assert: ((self isInSegments: (segments at: i) segLimit) not
  						or: [i < (numSegments - 1)
  							and: [(segments at: i) segLimit = (segments at: i + 1) segStart]]).
  			self assert: ((self isInSegments: (segments at: i) segStart - manager wordSize) not
  							or: [i > 0
  								and: [(segments at: i - 1) segLimit = (segments at: i) segStart]])].
  		 ^newSeg].
  	^nil!

Item was changed:
  ----- Method: SpurSelectiveCompactor>>freeSegment: (in category 'segment access') -----
  freeSegment: segInfo
  	<var: 'segInfo' type: #'SpurSegmentInfo *'>
+ 	 "self unmarkSegmentAsBeingCompacted: segInfo. 'For assertion in free chunk management'."
  	 manager addFreeChunkWithBytes: segInfo segSize - manager bridgeSize at: segInfo segStart.!

Item was added:
+ ----- Method: SpurSelectiveCompactor>>unmarkSegmentAsBeingCompacted: (in category 'segment access') -----
+ unmarkSegmentAsBeingCompacted: segInfo 
+ 	<inline: true> "So it is not generated if unused"
+ 	<var: 'segInfo' type: #'SpurSegmentInfo *'>
+ 	"Swizzle is abused bit 16 isBeingCompacted bits 0-15 occupation"
+ 	segInfo swizzle: (segInfo swizzle bitAnd: 16rFFFF)!

Item was changed:
  ----- Method: SpurSelectiveCompactorSimulator>>checkSegmentToFillLooksAllRight (in category 'debugging') -----
  checkSegmentToFillLooksAllRight
  	"Check only 1 free object at the end or none.
  	 Check segment is iterable until bridge"
  	| currentEntity bridge |
  	self talk: 'Checking segment to fill iterable/last is free ' , (manager segmentManager indexOfSegment: segmentToFill) printString.
  	bridge := manager segmentManager bridgeFor: segmentToFill.
  	currentEntity := manager objectStartingAt: segmentToFill segStart.
  	[self oop: currentEntity isLessThan: bridge] whileTrue: 
  		[(manager isFreeObject: currentEntity) 
  			ifTrue: "should be last entity"
  				[self assert: (manager objectAfter: currentEntity limit: manager endOfMemory) = bridge.
+ 				 manager assertValidFreeObject: currentEntity].
- 				 self assertValidFreeObject: currentEntity].
  		 currentEntity := manager objectAfter: currentEntity limit: manager endOfMemory].
  	"End of iteration should end on bridge"
  	self assert: currentEntity = bridge.
  	self talkNoCr: ' OK'.!



More information about the Vm-dev mailing list