[Vm-dev] VM Maker: VMMaker.oscog-cb.2390.mcz
commits at source.squeak.org
commits at source.squeak.org
Tue May 29 14:14:57 UTC 2018
ClementBera uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-cb.2390.mcz
==================== Summary ====================
Name: VMMaker.oscog-cb.2390
Author: cb
Time: 29 May 2018, 4:10:06.474615 pm
UUID: 24984602-b70a-4b9c-af24-2ff42f844c26
Ancestors: VMMaker.oscog-cb.2389
Fixed consistency checks in VMClass to succeed if no compactorClass is present.
Fixed simulation of segments to re-use correctly memory. It used to be badly broken (sometimes the simulator would think there is enough room for segment + delta, but there wasn't; other segments would just overlap each other entirely).
Added segmentOverlap assertions and debugging convenience.
Finally I have the same bug in the simulator than in the real C VM! I can debug my compactor again.
=============== Diff against VMMaker.oscog-cb.2389 ===============
Item was changed:
----- Method: SpurMemoryManager>>sqAllocateMemorySegmentOfSize:Above:AllocatedSizeInto: (in category 'simulation only') -----
sqAllocateMemorySegmentOfSize: segmentSize Above: minAddress AllocatedSizeInto: allocSizePtrOrBlock
<doNotGenerate>
"Simulate heap growth by growing memory by segmentSize + a delta.
To test bridges alternate the delta between 0 bytes and 1M bytes
depending on the number of segments.
The delta will be the distance between segments to be bridged."
| delta newMemory start |
self assert: segmentSize \\ memory bytesPerElement = 0.
delta := segmentManager numSegments odd ifTrue: [1024 * 1024] ifFalse: [0].
+ "A previous shrink may have freed up memory. Don't bother to grow if there's already room.
+ At minAddress there is a hole of segmentSize or it is the segLimit of the last segment.
+ However there is no hole of segmentSize + delta guaranteed..."
+ 0 to: segmentManager numSegments - 1 do:
+ [:i| | segment bridge |
+ segment := segmentManager segments at: i.
+ bridge := segmentManager bridgeAt: i.
+ (segment segLimit >= minAddress
+ and: [(self bytesInObject: bridge) - self bridgeSize >= (segmentSize + delta)]) ifTrue: [
+ allocSizePtrOrBlock value: segmentSize.
+ ^ segment segLimit + delta] ].
- "A previous shrink may have freed up memory. Don't bother to grow if there's already room."
- segmentManager lastSegment segLimit + segmentSize + delta <= (memory size * memory bytesPerElement) ifTrue:
- [allocSizePtrOrBlock value: segmentSize.
- ^minAddress + delta].
start := memory size * memory bytesPerElement + delta.
newMemory := memory class new: memory size + (segmentSize + delta / memory bytesPerElement).
newMemory replaceFrom: 1 to: memory size with: memory startingAt: 1.
memory := newMemory.
allocSizePtrOrBlock value: segmentSize.
^start!
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.
+ 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: SpurSegmentManager>>bridgeFrom:to: (in category 'growing/shrinking memory') -----
bridgeFrom: aSegment to: nextSegmentOrNil
"Create a bridge from aSegment to the next segment,
or create a terminating bridge if there is no next segment."
<var: #aSegment type: #'SpurSegmentInfo *'>
<var: #nextSegmentOrNil type: #'SpurSegmentInfo *'>
| segEnd clifton bridgeSpan |
segEnd := aSegment segLimit.
clifton := segEnd - manager bridgeSize. "clifton is where the Avon bridge begins..."
bridgeSpan := nextSegmentOrNil
ifNil: [manager bridgeSize]
ifNotNil: [nextSegmentOrNil segStart - segEnd + manager bridgeSize].
+ self assert: bridgeSpan >= 0.
manager initSegmentBridgeWithBytes: bridgeSpan at: clifton.
"the revised bridge should get us to the new segment"
self assert: (manager addressAfter: (manager objectStartingAt: clifton))
= (nextSegmentOrNil
ifNil: [aSegment segLimit]
ifNotNil: [nextSegmentOrNil segStart])
!
Item was added:
+ ----- Method: SpurSegmentManager>>printSegmentAddresses (in category 'simulation only') -----
+ printSegmentAddresses
+ <doNotGenerate>
+ "Convenient when debugging segment overlap"
+ Transcript show: 'Seg addresses: '; cr.
+ 0 to: numSegments - 1 do:
+ [:i|
+ Transcript
+ show: (segments at: i) segStart;
+ show: ' -> ';
+ show: (segments at: i) segLimit;
+ show: ' ; '].
+ Transcript cr.!
Item was added:
+ ----- Method: SpurSegmentManager>>segmentOverlap (in category 'growing/shrinking memory') -----
+ segmentOverlap
+ "Answers true if a segment overlaps with another one."
+ 0 to: numSegments - 1 do:
+ [:i| | starti endi |
+ starti := (segments at: i) segStart.
+ endi := (segments at: i) segLimit.
+ 0 to: numSegments - 1 do:
+ [:j| | startj endj |
+ startj := (segments at: j) segStart.
+ endj := (segments at: j) segLimit.
+ i = j ifFalse:
+ [(starti < startj or: [starti >= endj])
+ ifFalse:
+ [self cCode: '' inSmalltalk: [self error: 'segment overlap ' , i printString , ' and ' , j printString].
+ ^true].
+ (endi <= startj or: [endi >= endj])
+ ifFalse: [self cCode: '' inSmalltalk: [self error: 'segment overlap ' , i printString , ' and ' , j printString].
+ ^true].
+ "self printSegmentAddresses"
+ ]]].
+ ^false!
Item was changed:
----- Method: VMClass class>>initializeMiscConstants (in category 'initialization') -----
initializeMiscConstants
"Falsify the `what type of VM is this?' flags that are defined in the various interp.h files.
Subclass implementations need to include a super initializeMiscConstants"
| omc |
VMBIGENDIAN class. "Mention this for the benefit of CCodeGenerator>>emitCConstantsOn:"
SPURVM := STACKVM := COGVM := COGMTVM := false.
initializationOptions ifNil: [self initializationOptions: Dictionary new].
omc := initializationOptions at: #ObjectMemory ifAbsent: nil.
(omc isNil and: [self defaultObjectMemoryClass notNil]) ifTrue:
[omc := initializationOptions at: #ObjectMemory put: self defaultObjectMemoryClass name].
initializationOptions
at: #SqueakV3ObjectMemory "the good ole default"
ifAbsentPut: (omc
ifNil: [true]
ifNotNil: [(Smalltalk at: omc) includesBehavior: ObjectMemory]);
at: #SpurObjectMemory "the new contender"
ifAbsentPut: (omc
ifNil: [false]
ifNotNil: [(Smalltalk at: omc) includesBehavior: SpurMemoryManager]).
"Use ifAbsentPut: so that they will get copied back to the
VMMaker's options and dead code will likely be eliminated."
PharoVM := initializationOptions at: #PharoVM ifAbsentPut: [false].
NewspeakVM := initializationOptions at: #NewspeakVM ifAbsentPut: [false].
SistaVM := initializationOptions at: #SistaVM ifAbsentPut: [false].
TempVectReadBarrier := initializationOptions at: #TempVectReadBarrier ifAbsentPut: [false].
LowcodeVM := initializationOptions at: #LowcodeVM ifAbsentPut: [false].
MULTIPLEBYTECODESETS := initializationOptions at: #MULTIPLEBYTECODESETS ifAbsentPut: [false].
"These must be set only if specified, not defaulted, because they are set on the command line or in include files."
initializationOptions
at: #VMBIGENDIAN ifPresent: [:value| VMBIGENDIAN := value];
at: #ObjectMemory ifPresent: [:value| SPURVM := value beginsWith: 'Spur'];
at: #STACKVM ifPresent: [:value| STACKVM := value];
at: #COGVM ifPresent: [:value| COGVM := initializationOptions at: #COGVM];
at: #COGMTVM ifPresent: [:value| COGMTVM := initializationOptions at: #COGMTVM].
"consistency checks"
(TempVectReadBarrier and: [SPURVM not]) ifTrue: [self error: 'read barrier works with spur VM only...'].
(SistaVM and: [SPURVM not]) ifTrue: [self error: 'Sista VM works with spur VM only...'].
+ ((initializationOptions at: #compactorClass ifAbsent: []) = #SpurSelectiveCompactor and: [TempVectReadBarrier not]) ifTrue: [self error: 'Selective compactor requires read barrier'].
- ((initializationOptions at: #compactorClass) = #SpurSelectiveCompactor and: [TempVectReadBarrier not]) ifTrue: [self error: 'Selective compactor requires read barrier'].
"And not these; they're compile-time"
IMMUTABILITY := initializationOptions at: #IMMUTABILITY ifAbsent: [SPURVM] "Default as enabled for Spur VMs"!
More information about the Vm-dev
mailing list