[Vm-dev] VM Maker: VMMaker.oscog-eem.1113.mcz

commits at source.squeak.org commits at source.squeak.org
Mon Mar 23 19:54:14 UTC 2015


Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1113.mcz

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

Name: VMMaker.oscog-eem.1113
Author: eem
Time: 23 March 2015, 12:52:02.301 pm
UUID: 9b08eea7-d3db-440f-ba64-16abc799fcf8
Ancestors: VMMaker.oscog-eem.1112

Redo free space allocation on Spur image load.
Provide a minimum ammount of free space, taking
into account extant free space.  Provisionally use
extraVMMemory in the header, defaulting to
growHeadroom if extraVMMemory is empty.
This can be revised if folks protest.

=============== Diff against VMMaker.oscog-eem.1112 ===============

Item was changed:
  ----- Method: CoInterpreter>>readImageFromFile:HeapSize:StartingAt: (in category 'image save/restore') -----
  readImageFromFile: f HeapSize: desiredHeapSize StartingAt: imageOffset
+ 	"Read an image from the given file stream, allocating an amount of memory to its object heap.
+ 	
+ 	 V3: desiredHeapSize is the total size of the heap.  Fail if the image has an unknown format or
+ 	 requires more than the specified amount of memory.
- 	"Read an image from the given file stream, allocating the given amount of memory to its object heap. Fail if the image has an unknown format or requires more than the given amount of memory."
- 	"Details: This method detects when the image was stored on a machine with the opposite byte ordering from this machine and swaps the bytes automatically. Furthermore, it allows the header information to start 512 bytes into the file, since some file transfer programs for the Macintosh apparently prepend a Mac-specific header of this size. Note that this same 512 bytes of prefix area could also be used to store an exec command on Unix systems, allowing one to launch Smalltalk by invoking the image name as a command."
- 	"This code is based on C code by Ian Piumarta and Smalltalk code by Tim Rowledge. Many thanks to both of you!!!!"
  
+ 	 Spur: desiredHeapSize is ignored; this routine will attempt to provide at least extraVMMemory's
+ 	 ammount of free space after the image is loaded, taking any free space in teh image into account.
+ 	 extraVMMemory is stored in the image header and is accessible as vmParameterAt: 23.  If
+ 	 extraVMMemory is 0, the value defaults to the default grow headroom.  Fail if the image has an
+ 	 unknown format or if sufficient memory cannot be allocated.
+ 
+ 	 Details: This method detects when the image was stored on a machine with the opposite byte
+ 	 ordering from this machine and swaps the bytes automatically. Furthermore, it allows the header
+ 	 information to start 512 bytes into the file, since some file transfer programs for the Macintosh
+ 	 apparently prepend a Mac-specific header of this size. Note that this same 512 bytes of prefix
+ 	 area could also be used to store an exec command on Unix systems, allowing one to launch
+ 	 Smalltalk by invoking the image name as a command."
+ 
  	| swapBytes headerStart headerSize dataSize oldBaseAddr
  	  minimumMemory heapSize bytesRead bytesToShift firstSegSize
+ 	  hdrNumStackPages hdrEdenBytes hdrCogCodeSize headerFlags hdrMaxExtSemTabSize allocationReserve |
- 	  hdrNumStackPages hdrEdenBytes hdrCogCodeSize headerFlags hdrMaxExtSemTabSize |
  	<var: #f type: #sqImageFile>
  	<var: #heapSize type: #usqInt>
  	<var: #dataSize type: #'size_t'>
  	<var: #minimumMemory type: #usqInt>
  	<var: #desiredHeapSize type: #usqInt>
+ 	<var: #allocationReserve type: #usqInt>
  	<var: #headerStart type: #squeakFileOffsetType>
  	<var: #imageOffset type: #squeakFileOffsetType>
  
  	metaclassNumSlots := 6.	"guess Metaclass instSize"
  	classNameIndex := 6.		"guess (Class instVarIndexFor: 'name' ifAbsent: []) - 1"
  	swapBytes := self checkImageVersionFrom: f startingAt: imageOffset.
  	headerStart := (self sqImageFilePosition: f) - 4.  "record header start position"
  
  	headerSize			:= self getWord32FromFile: f swap: swapBytes.
  	dataSize			:= self getLongFromFile: f swap: swapBytes.
  	oldBaseAddr		:= self getLongFromFile: f swap: swapBytes.
  	objectMemory specialObjectsOop: (self getLongFromFile: f swap: swapBytes).
  	objectMemory lastHash: (self getLongFromFile: f swap: swapBytes). "N.B.  not used."
  	savedWindowSize	:= self getLongFromFile: f swap: swapBytes.
  	headerFlags		:= self getLongFromFile: f swap: swapBytes.
  	self setImageHeaderFlagsFrom: headerFlags.
+ 	extraVMMemory	:= self getWord32FromFile: f swap: swapBytes. "N.B.  ignored in V3."
- 	extraVMMemory	:= self getWord32FromFile: f swap: swapBytes. "N.B.  not used."
  	hdrNumStackPages	:= self getShortFromFile: f swap: swapBytes.
  	"4 stack pages is small.  Should be able to run with as few as
  	 three. 4 should be comfortable but slow.  8 is a reasonable
  	 default.  Can be changed via vmParameterAt: 43 put: n.
  	 Can be set as a preference (Info.plist, VM.ini, command line etc).
  	 If desiredNumStackPages is already non-zero then it has been
  	 set as a preference.  Ignore (but preserve) the header's default."
  	numStackPages := desiredNumStackPages ~= 0
  						ifTrue: [desiredNumStackPages]
  						ifFalse: [hdrNumStackPages = 0
  									ifTrue: [self defaultNumStackPages]
  									ifFalse: [hdrNumStackPages]].
  	desiredNumStackPages := hdrNumStackPages.
  	"This slot holds the size of the native method zone in 1k units. (pad to word boundary)."
  	hdrCogCodeSize := (self getShortFromFile: f swap: swapBytes) * 1024.
  	cogCodeSize := desiredCogCodeSize ~= 0
  						ifTrue: [desiredCogCodeSize]
  						ifFalse:
  							[hdrCogCodeSize = 0
  									ifTrue: [self defaultCogCodeSize]
  									ifFalse: [hdrCogCodeSize]].
  	hdrEdenBytes		:= self getWord32FromFile: f swap: swapBytes.
  	objectMemory edenBytes: (desiredEdenBytes ~= 0
  						ifTrue: [desiredEdenBytes]
  						ifFalse:
  							[hdrEdenBytes = 0
  									ifTrue: [objectMemory defaultEdenBytes]
  									ifFalse: [hdrEdenBytes]]).
  	desiredEdenBytes := hdrEdenBytes.
  	hdrMaxExtSemTabSize := self getShortFromFile: f swap: swapBytes.
  	hdrMaxExtSemTabSize ~= 0 ifTrue:
  		[self setMaxExtSemSizeTo: hdrMaxExtSemTabSize].
  	"pad to word boundary.  This slot can be used for anything else that will fit in 16 bits.
  	 Preserve it to be polite to other VMs."
  	the2ndUnknownShort	:= self getShortFromFile: f swap: swapBytes.
  	firstSegSize := self getLongFromFile: f swap: swapBytes.
  	objectMemory firstSegmentSize: firstSegSize.
  
  	"compare memory requirements with availability"
+ 	allocationReserve := self interpreterAllocationReserveBytes.
  	minimumMemory := cogCodeSize "no need to include the stackZone; this is alloca'ed"
  						+ dataSize
  						+ objectMemory newSpaceBytes
+ 						+ allocationReserve.
+ 	objectMemory hasSpurMemoryManagerAPI
+ 		ifTrue:
+ 			[| freeOldSpaceInImage headroom |
+ 			 freeOldSpaceInImage := self getLongFromFile: f swap: swapBytes.
+ 			 headroom := objectMemory
+ 							initialHeadroom: extraVMMemory
+ 							givenFreeOldSpaceInImage: freeOldSpaceInImage.
+ 			 heapSize := objectMemory roundUpHeapSize:
+ 						   cogCodeSize "no need to include the stackZone; this is alloca'ed"
+ 						+ dataSize
+ 						+ headroom
+ 						+ objectMemory newSpaceBytes
+ 						+ (headroom > allocationReserve
+ 							ifTrue: [0]
+ 							ifFalse: [allocationReserve])]
+ 		ifFalse:
+ 			[heapSize :=  cogCodeSize "no need to include the stackZone; this is alloca'ed"
- 						+ self interpreterAllocationReserveBytes.
- 	heapSize             :=  cogCodeSize "no need to include the stackZone; this is alloca'ed"
  						+ desiredHeapSize
  						+ objectMemory newSpaceBytes
+ 						+ (desiredHeapSize - dataSize > allocationReserve
+ 							ifTrue: [0]
+ 							ifFalse: [allocationReserve]).
+ 			 heapSize < minimumMemory ifTrue:
+ 				[self insufficientMemorySpecifiedError]].
- 						+ self interpreterAllocationReserveBytes.
- 	heapSize < minimumMemory ifTrue:
- 		[self insufficientMemorySpecifiedError].
  
  	"allocate a contiguous block of memory for the Squeak heap and ancilliary data structures"
  	objectMemory memory: (self
  								allocateMemory: heapSize
  								minimum: minimumMemory
  								imageFile: f
  								headerSize: headerSize) asUnsignedInteger.
+ 	objectMemory memory ifNil:
+ 		[self insufficientMemoryAvailableError].
- 	objectMemory memory ifNil: [self insufficientMemoryAvailableError].
  
  	heapBase := objectMemory
  					setHeapBase: objectMemory memory + cogCodeSize
  					memoryLimit: objectMemory memory + heapSize
  					endOfMemory: objectMemory memory + cogCodeSize + dataSize.
  
  	"position file after the header"
  	self sqImageFile: f Seek: headerStart + headerSize.
  
  	"read in the image in bulk, then swap the bytes if necessary"
  	bytesRead := objectMemory readHeapFromImageFile: f dataBytes: dataSize.
  	bytesRead ~= dataSize ifTrue: [self unableToReadImageError].
  
  	self ensureImageFormatIsUpToDate: swapBytes.
  
  	"compute difference between old and new memory base addresses"
  	bytesToShift := objectMemory memoryBaseForImageRead - oldBaseAddr.
  	self initializeInterpreter: bytesToShift.  "adjusts all oops to new location"
  	self initializeCodeGenerator.
  	^dataSize!

Item was changed:
  ----- Method: CogVMSimulator>>openOn:extraMemory: (in category 'initialization') -----
  openOn: fileName extraMemory: extraBytes
  	"CogVMSimulator new openOn: 'clone.im' extraMemory: 100000"
  
  	| f version headerSize dataSize count oldBaseAddr bytesToShift swapBytes
  	  headerFlags firstSegSize heapSize
  	  hdrNumStackPages hdrEdenBytes hdrMaxExtSemTabSize
+ 	  hdrCogCodeSize stackZoneSize methodCacheSize primTraceLogSize allocationReserve |
- 	  hdrCogCodeSize stackZoneSize methodCacheSize primTraceLogSize |
  	"open image file and read the header"
  
  	f := FileStream readOnlyFileNamed: fileName.
  	f ifNil: [^self error: 'no image found'].
  
  	["begin ensure block..."
  	imageName := f fullName.
  	f binary.
  
  	version := self getWord32FromFile: f swap: false.  "current version: 16r1968 (=6504) vive la revolucion!!"
  	(self readableFormat: version)
  		ifTrue: [swapBytes := false]
  		ifFalse: [(version := objectMemory byteSwapped: version) = self imageFormatVersion
  					ifTrue: [swapBytes := true]
  					ifFalse: [self error: 'incomaptible image format']].
  	headerSize := self getWord32FromFile: f swap: swapBytes.
  	dataSize := self getLongFromFile: f swap: swapBytes.  "length of heap in file"
  	oldBaseAddr := self getLongFromFile: f swap: swapBytes.  "object memory base address of image"
  	objectMemory specialObjectsOop: (self getLongFromFile: f swap: swapBytes).
  	objectMemory lastHash: (self getLongFromFile: f swap: swapBytes).  "Should be loaded from, and saved to the image header"
  
  	savedWindowSize	:= self getLongFromFile: f swap: swapBytes.
  	headerFlags		:= self getLongFromFile: f swap: swapBytes.
  	self setImageHeaderFlagsFrom: headerFlags.
  	extraVMMemory	:= self getWord32FromFile: f swap: swapBytes.
  	hdrNumStackPages	:= self getShortFromFile: f swap: swapBytes.
  	"4 stack pages is small.  Should be able to run with as few as
  	 three. 4 should be comfortable but slow.  8 is a reasonable
  	 default. Can be changed via vmParameterAt: 43 put: n"
  	numStackPages := desiredNumStackPages ~= 0
  						ifTrue: [desiredNumStackPages]
  						ifFalse: [hdrNumStackPages = 0
  									ifTrue: [self defaultNumStackPages]
  									ifFalse: [hdrNumStackPages]].
  	desiredNumStackPages := hdrNumStackPages.
  	stackZoneSize := self computeStackZoneSize.
  	"This slot holds the size of the native method zone in 1k units. (pad to word boundary)."
  	hdrCogCodeSize := (self getShortFromFile: f swap: swapBytes) * 1024.
  	cogCodeSize := desiredCogCodeSize ~= 0
  						ifTrue: [desiredCogCodeSize]
  						ifFalse:
  							[hdrCogCodeSize = 0
  									ifTrue: [self defaultCogCodeSize]
  									ifFalse: [hdrCogCodeSize]].
  	desiredCogCodeSize := hdrCogCodeSize.
  	self assert: f position = (objectMemory wordSize = 4 ifTrue: [40] ifFalse: [64]).
  	hdrEdenBytes	:= self getWord32FromFile: f swap: swapBytes.
  	objectMemory edenBytes: (desiredEdenBytes ~= 0
  						ifTrue: [desiredEdenBytes]
  						ifFalse:
  							[hdrEdenBytes = 0
  									ifTrue: [objectMemory defaultEdenBytes]
  									ifFalse: [hdrEdenBytes]]).
  	desiredEdenBytes := hdrEdenBytes.
  	hdrMaxExtSemTabSize := self getShortFromFile: f swap: swapBytes.
  	hdrMaxExtSemTabSize ~= 0 ifTrue:
  		[self setMaxExtSemSizeTo: hdrMaxExtSemTabSize].
  	"pad to word boundary.  This slot can be used for anything else that will fit in 16 bits.
  	 Preserve it to be polite to other VMs."
  	the2ndUnknownShort	:= self getShortFromFile: f swap: swapBytes.
  	self assert: f position = (objectMemory wordSize = 4 ifTrue: [48] ifFalse: [72]).
  	firstSegSize := self getLongFromFile: f swap: swapBytes.
  	objectMemory firstSegmentSize: firstSegSize.
  	"For Open PICs to be able to probe the method cache during
  	 simulation the methodCache must be relocated to memory."
  	methodCacheSize := methodCache size * objectMemory wordSize.
  	primTraceLogSize := primTraceLog size * objectMemory wordSize.
  	"allocate interpreter memory. This list is in address order, low to high.
  	 In the actual VM the stack zone exists on the C stack."
  	heapBase := (Cogit guardPageSize
  				+ cogCodeSize
  				+ stackZoneSize
  				+ methodCacheSize
  				+ primTraceLogSize
  				+ self rumpCStackSize) roundUpTo: objectMemory allocationUnit.
+ 	"compare memory requirements with availability"
+ 	allocationReserve := self interpreterAllocationReserveBytes.
+ 	objectMemory hasSpurMemoryManagerAPI
+ 		ifTrue:
+ 			[| freeOldSpaceInImage headroom |
+ 			 freeOldSpaceInImage := self getLongFromFile: f swap: swapBytes.
+ 			 headroom := objectMemory
+ 							initialHeadroom: extraVMMemory
+ 							givenFreeOldSpaceInImage: freeOldSpaceInImage.
+ 			 heapSize := objectMemory roundUpHeapSize:
+ 						   dataSize
+ 						+ headroom
+ 						+ objectMemory newSpaceBytes
+ 						+ (headroom > allocationReserve
+ 							ifTrue: [0]
+ 							ifFalse: [allocationReserve])]
+ 		ifFalse:
+ 			[heapSize :=  dataSize
+ 						+ extraBytes
+ 						+ objectMemory newSpaceBytes
+ 						+ (extraBytes > allocationReserve
+ 							ifTrue: [0]
+ 							ifFalse: [allocationReserve])].
- 	heapSize := dataSize
- 				+ extraBytes
- 				+ objectMemory newSpaceBytes
- 				+ self interpreterAllocationReserveBytes
- 				+ (objectMemory hasSpurMemoryManagerAPI
- 					ifTrue: [headerSize]
- 					ifFalse: [0]).
  	heapBase := objectMemory
  					setHeapBase: heapBase
  					memoryLimit:  heapBase + heapSize
  					endOfMemory: heapBase + dataSize.
  
  	self assert: cogCodeSize \\ 4 = 0.
  	self assert: objectMemory memoryLimit \\ 4 = 0.
  	self assert: self rumpCStackSize \\ 4 = 0.
  	"read in the image in bulk, then swap the bytes if necessary"
  	f position: headerSize.
  	objectMemory memory: ((cogit processor endianness == #little
  					ifTrue: [LittleEndianBitmap]
  					ifFalse: [Bitmap]) new: objectMemory memoryLimit // 4).
  	count := objectMemory readHeapFromImageFile: f dataBytes: dataSize.
  	count ~= dataSize ifTrue: [self halt].
  	]
  		ensure: [f close].
  	self moveMethodCacheToMemoryAt: objectMemory cogCodeBase + cogCodeSize + stackZoneSize.
  	self movePrimTraceLogToMemoryAt: objectMemory cogCodeBase + cogCodeSize + stackZoneSize + methodCacheSize.
  
  	self ensureImageFormatIsUpToDate: swapBytes.
  
  	bytesToShift := objectMemory memoryBaseForImageRead - oldBaseAddr.  "adjust pointers for zero base address"
  	Utilities
  		informUser: 'Relocating object pointers...'
  		during: [self initializeInterpreter: bytesToShift].
  	self initializeCodeGenerator!

Item was added:
+ ----- Method: SpurMemoryManager>>initialHeadroom:givenFreeOldSpaceInImage: (in category 'snapshot') -----
+ initialHeadroom: extraVmMemory givenFreeOldSpaceInImage: freeOldSpaceInImage
+ 	"Answer how much headroom to allocate, if any, on loading the image.
+ 	 If the image already conatins lots of free space, we should not allocate lots more."
+ 	<inline: true>
+ 	| headroom |
+ 	headroom := extraVmMemory = 0
+ 					ifTrue: [growHeadroom ifNil: [16*1024*1024]]
+ 					ifFalse: [extraVmMemory].
+ 	freeOldSpaceInImage >= headroom ifTrue:
+ 		[^0].
+ 	freeOldSpaceInImage >= (headroom * 7 // 8) ifTrue:
+ 		[^headroom // 8].
+ 	freeOldSpaceInImage >= (headroom * 3 // 4) ifTrue:
+ 		[^headroom // 4].
+ 	freeOldSpaceInImage >= (headroom * 5 // 8) ifTrue:
+ 		[^headroom * 3 // 8].
+ 	freeOldSpaceInImage >= (headroom // 2) ifTrue:
+ 		[^headroom // 2].
+ 	^headroom!

Item was added:
+ ----- Method: SpurMemoryManager>>roundUpHeapSize: (in category 'snapshot') -----
+ roundUpHeapSize: heapSize
+ 	<var: 'heapSize' type: #usqInt>
+ 	| bit |
+ 	bit := heapSize highBit - 1 * 3 // 4.
+ 	^(heapSize anyMask: (1 << bit - 1))
+ 		ifTrue: [(heapSize bitClear: (1 << bit - 1)) + (1 << bit)]
+ 		ifFalse: [heapSize]!

Item was changed:
  ----- Method: StackInterpreter>>openOn: (in category 'simulation') -----
  openOn: fileName
  	"(StackInterpreterSimulator new openOn: 'clonex.image') openAsMorph; run"
  	<doNotGenerate>
- 	objectMemory hasSpurMemoryManagerAPI ifTrue:
- 		[| fileSize potSize |
- 		fileSize := (FileDirectory directoryEntryFor: fileName)
- 						ifNotNil: [:ent| ent fileSize]
- 						ifNil: [((FileDoesNotExistException fileName: fileName) readOnly: true) signal].
- 		potSize := 1 << (fileSize - 1) highBit.
- 		^self openOn: fileName extraMemory: potSize / 4 + potSize - fileSize].
  	self openOn: fileName extraMemory: 2500000!

Item was changed:
  ----- Method: StackInterpreter>>readImageFromFile:HeapSize:StartingAt: (in category 'image save/restore') -----
  readImageFromFile: f HeapSize: desiredHeapSize StartingAt: imageOffset
+ 	"Read an image from the given file stream, allocating an amount of memory to its object heap.
+ 	
+ 	 V3: desiredHeapSize is the total size of the heap.  Fail if the image has an unknown format or
+ 	 requires more than the specified amount of memory.
- 	"Read an image from the given file stream, allocating the given amount of memory to its object heap. Fail if the image has an unknown format or requires more than the given amount of memory."
- 	"Details: This method detects when the image was stored on a machine with the opposite byte ordering from this machine and swaps the bytes automatically. Furthermore, it allows the header information to start 512 bytes into the file, since some file transfer programs for the Macintosh apparently prepend a Mac-specific header of this size. Note that this same 512 bytes of prefix area could also be used to store an exec command on Unix systems, allowing one to launch Smalltalk by invoking the image name as a command."
- 	"This code is based on C code by Ian Piumarta and Smalltalk code by Tim Rowledge. Many thanks to both of you!!!!"
  
+ 	 Spur: desiredHeapSize is ignored; this routine will attempt to provide at least extraVMMemory's
+ 	 ammount of free space after the image is loaded, taking any free space in teh image into account.
+ 	 extraVMMemory is stored in the image header and is accessible as vmParameterAt: 23.  If
+ 	 extraVMMemory is 0, the value defaults to the default grow headroom.  Fail if the image has an
+ 	 unknown format or if sufficient memory cannot be allocated.
+ 
+ 	 Details: This method detects when the image was stored on a machine with the opposite byte
+ 	 ordering from this machine and swaps the bytes automatically. Furthermore, it allows the header
+ 	 information to start 512 bytes into the file, since some file transfer programs for the Macintosh
+ 	 apparently prepend a Mac-specific header of this size. Note that this same 512 bytes of prefix
+ 	 area could also be used to store an exec command on Unix systems, allowing one to launch
+ 	 Smalltalk by invoking the image name as a command."
+ 
  	| headerStart headerSize headerFlags dataSize oldBaseAddr swapBytes
  	  minimumMemory bytesRead bytesToShift heapSize firstSegSize
+ 	  hdrEdenBytes hdrMaxExtSemTabSize hdrNumStackPages allocationReserve |
- 	  hdrEdenBytes hdrMaxExtSemTabSize hdrNumStackPages |
  	<var: #f type: #sqImageFile>
  	<var: #heapSize type: #usqInt>
  	<var: #dataSize type: #'size_t'>
  	<var: #minimumMemory type: #usqInt>
  	<var: #desiredHeapSize type: #usqInt>
+ 	<var: #allocationReserve type: #usqInt>
  	<var: #headerStart type: #squeakFileOffsetType>
  	<var: #imageOffset type: #squeakFileOffsetType>
  
  	metaclassNumSlots := 6.	"guess Metaclass instSize"
  	classNameIndex := 6.		"guess (Class instVarIndexFor: 'name' ifAbsent: []) - 1"
  	swapBytes := self checkImageVersionFrom: f startingAt: imageOffset.
  	headerStart := (self sqImageFilePosition: f) - 4.  "record header start position"
  
  	headerSize			:= self getWord32FromFile: f swap: swapBytes.
  	dataSize			:= self getLongFromFile: f swap: swapBytes.
  	oldBaseAddr		:= self getLongFromFile: f swap: swapBytes.
  	objectMemory specialObjectsOop: (self getLongFromFile: f swap: swapBytes).
  	objectMemory lastHash: (self getLongFromFile: f swap: swapBytes). "N.B.  not used."
  	savedWindowSize	:= self getLongFromFile: f swap: swapBytes.
  	headerFlags		:= self getLongFromFile: f swap: swapBytes.
  	self setImageHeaderFlagsFrom: headerFlags.
  	extraVMMemory	:= self getWord32FromFile: f swap: swapBytes.
  	hdrNumStackPages	:= self getShortFromFile: f swap: swapBytes.
  	"4 stack pages is small.  Should be able to run with as few as
  	 three. 4 should be comfortable but slow.  8 is a reasonable
  	 default.  Can be changed via vmParameterAt: 43 put: n.
  	 Can be set as a preference (Info.plist, VM.ini, command line etc).
  	 If desiredNumStackPages is already non-zero then it has been
  	 set as a preference.  Ignore (but preserve) the header's default."
  	numStackPages := desiredNumStackPages ~= 0
  						ifTrue: [desiredNumStackPages]
  						ifFalse: [hdrNumStackPages = 0
  									ifTrue: [self defaultNumStackPages]
  									ifFalse: [hdrNumStackPages]].
  	desiredNumStackPages := hdrNumStackPages.
  	"pad to word boundary.  This slot can be used for anything else that will fit in 16 bits.
  	 It is used for the cog code size in Cog.  Preserve it to be polite to other VMs."
  	theUnknownShort	:= self getShortFromFile: f swap: swapBytes.
  	hdrEdenBytes		:= self getWord32FromFile: f swap: swapBytes.
  	objectMemory edenBytes: (desiredEdenBytes ~= 0
  						ifTrue: [desiredEdenBytes]
  						ifFalse:
  							[hdrEdenBytes = 0
  									ifTrue: [objectMemory defaultEdenBytes]
  									ifFalse: [hdrEdenBytes]]).
  	desiredEdenBytes := hdrEdenBytes.
  	hdrMaxExtSemTabSize := self getShortFromFile: f swap: swapBytes.
  	hdrMaxExtSemTabSize ~= 0 ifTrue:
  		[self setMaxExtSemSizeTo: hdrMaxExtSemTabSize].
  	"pad to word boundary.  This slot can be used for anything else that will fit in 16 bits.
  	 Preserve it to be polite to other VMs."
  	the2ndUnknownShort	:= self getShortFromFile: f swap: swapBytes.
  	firstSegSize := self getLongFromFile: f swap: swapBytes.
  	objectMemory firstSegmentSize: firstSegSize.
+ 	"compare memory requirements with availability"
+ 	allocationReserve := self interpreterAllocationReserveBytes.
+ 	minimumMemory := dataSize
+ 						+ objectMemory newSpaceBytes
+ 						+ allocationReserve.
+ 	objectMemory hasSpurMemoryManagerAPI
+ 		ifTrue:
+ 			[| freeOldSpaceInImage headroom |
+ 			 freeOldSpaceInImage := self getLongFromFile: f swap: swapBytes.
+ 			 headroom := objectMemory
+ 							initialHeadroom: extraVMMemory
+ 							givenFreeOldSpaceInImage: freeOldSpaceInImage.
+ 			 heapSize := objectMemory roundUpHeapSize:
+ 						   dataSize
+ 						+ headroom
+ 						+ objectMemory newSpaceBytes
+ 						+ (headroom > allocationReserve
+ 							ifTrue: [0]
+ 							ifFalse: [allocationReserve])]
+ 		ifFalse:
+ 			[heapSize :=  desiredHeapSize
+ 						+ objectMemory newSpaceBytes
+ 						+ (desiredHeapSize - dataSize > allocationReserve
+ 							ifTrue: [0]
+ 							ifFalse: [allocationReserve]).
+ 			 heapSize < minimumMemory ifTrue:
+ 				[self insufficientMemorySpecifiedError]].
- 	"decrease Squeak object heap to leave extra memory for the VM"
- 	heapSize := desiredHeapSize
- 				+ objectMemory newSpaceBytes
- 				+ self interpreterAllocationReserveBytes.
- 	heapSize := self reserveExtraCHeap: heapSize Bytes: extraVMMemory.
  
- 	"compare memory requirements with availability".
- 	minimumMemory := dataSize + objectMemory newSpaceBytes + self interpreterAllocationReserveBytes.
- 	heapSize < minimumMemory ifTrue:
- 		[self insufficientMemorySpecifiedError].
- 
  	"allocate a contiguous block of memory for the Squeak heap"
  	objectMemory memory: (self
  								allocateMemory: heapSize
  								minimum: minimumMemory
  								imageFile: f
  								headerSize: headerSize) asUnsignedInteger.
  	objectMemory memory ifNil: [self insufficientMemoryAvailableError].
  
  	objectMemory
  		setHeapBase: objectMemory memory
  		memoryLimit: objectMemory memory + heapSize
  		endOfMemory: objectMemory memory + dataSize.
  
  	"position file after the header"
  	self sqImageFile: f Seek: headerStart + headerSize.
  
  	"read in the image in bulk, then swap the bytes if necessary"
  	bytesRead := objectMemory readHeapFromImageFile: f dataBytes: dataSize.
  	bytesRead ~= dataSize ifTrue: [self unableToReadImageError].
  
  	self ensureImageFormatIsUpToDate: swapBytes.
  
  	"compute difference between old and new memory base addresses"
  	bytesToShift := objectMemory memoryBaseForImageRead - oldBaseAddr.
  	self initializeInterpreter: bytesToShift.  "adjusts all oops to new location"
  	^dataSize!

Item was changed:
  ----- Method: StackInterpreterSimulator>>openOn:extraMemory: (in category 'initialization') -----
  openOn: fileName extraMemory: extraBytes
  	"StackInterpreterSimulator new openOn: 'clone.im' extraMemory: 100000"
  
  	| f version headerSize dataSize count oldBaseAddr bytesToShift swapBytes
  	  headerFlags heapBase firstSegSize heapSize
+ 	  hdrNumStackPages hdrEdenBytes hdrMaxExtSemTabSize allocationReserve |
- 	  hdrNumStackPages hdrEdenBytes hdrMaxExtSemTabSize |
  	"open image file and read the header"
  
  	f := FileStream readOnlyFileNamed: fileName.
  	f ifNil: [^self error: 'no image found'].
  
  	["begin ensure block..."
  	imageName := f fullName.
  	f binary.
  
  	version := self getWord32FromFile: f swap: false.  "current version: 16r1968 (=6504) vive la revolucion!!"
  	(self readableFormat: version)
  		ifTrue: [swapBytes := false]
  		ifFalse: [(version := objectMemory byteSwapped: version) = self imageFormatVersion
  					ifTrue: [swapBytes := true]
  					ifFalse: [self error: 'incomaptible image format']].
  	headerSize := self getWord32FromFile: f swap: swapBytes.
  	dataSize := self getLongFromFile: f swap: swapBytes.  "length of heap in file"
  	oldBaseAddr := self getLongFromFile: f swap: swapBytes.  "object memory base address of image"
  	objectMemory specialObjectsOop: (self getLongFromFile: f swap: swapBytes).
  	objectMemory lastHash: (self getLongFromFile: f swap: swapBytes).  "Should be loaded from, and saved to the image header"
  
  	savedWindowSize	:= self getLongFromFile: f swap: swapBytes.
  	headerFlags		:= self getLongFromFile: f swap: swapBytes.
  	self setImageHeaderFlagsFrom: headerFlags.
  	extraVMMemory	:= self getWord32FromFile: f swap: swapBytes.
  	hdrNumStackPages	:= self getShortFromFile: f swap: swapBytes.
  	"4 stack pages is small.  Should be able to run with as few as
  	 three. 4 should be comfortable but slow.  8 is a reasonable
  	 default. Can be changed via vmParameterAt: 43 put: n"
  	numStackPages := desiredNumStackPages ~= 0
  						ifTrue: [desiredNumStackPages]
  						ifFalse: [hdrNumStackPages = 0
  									ifTrue: [self defaultNumStackPages]
  									ifFalse: [hdrNumStackPages]].
  	desiredNumStackPages := hdrNumStackPages.
  	"pad to word boundary.  This slot can be used for anything else that will fit in 16 bits.
  	 It is used for the cog code size in Cog.  Preserve it to be polite to other VMs."
  	theUnknownShort	:= self getShortFromFile: f swap: swapBytes.
  	self assert: f position = (objectMemory wordSize = 4 ifTrue: [40] ifFalse: [64]).
  	hdrEdenBytes		:= self getWord32FromFile: f swap: swapBytes.
  	objectMemory edenBytes: (hdrEdenBytes = 0
  							ifTrue: [objectMemory defaultEdenBytes]
  							ifFalse: [hdrEdenBytes]).
  	desiredEdenBytes := hdrEdenBytes.
  	hdrMaxExtSemTabSize := self getShortFromFile: f swap: swapBytes.
  	hdrMaxExtSemTabSize ~= 0 ifTrue:
  		[self setMaxExtSemSizeTo: hdrMaxExtSemTabSize].
  	"pad to word boundary.  This slot can be used for anything else that will fit in 16 bits.
  	 Preserve it to be polite to other VMs."
  	the2ndUnknownShort	:= self getShortFromFile: f swap: swapBytes.
  	self assert: f position = (objectMemory wordSize = 4 ifTrue: [48] ifFalse: [72]).
  	firstSegSize := self getLongFromFile: f swap: swapBytes.
  	objectMemory firstSegmentSize: firstSegSize.
+ 	"compare memory requirements with availability"
+ 	allocationReserve := self interpreterAllocationReserveBytes.
+ 	objectMemory hasSpurMemoryManagerAPI
+ 		ifTrue:
+ 			[| freeOldSpaceInImage headroom |
+ 			 freeOldSpaceInImage := self getLongFromFile: f swap: swapBytes.
+ 			 headroom := objectMemory
+ 							initialHeadroom: extraVMMemory
+ 							givenFreeOldSpaceInImage: freeOldSpaceInImage.
+ 			 heapSize := objectMemory roundUpHeapSize:
+ 						   dataSize
+ 						+ headroom
+ 						+ objectMemory newSpaceBytes
+ 						+ (headroom > allocationReserve
+ 							ifTrue: [0]
+ 							ifFalse: [allocationReserve])]
+ 		ifFalse:
+ 			[heapSize :=  dataSize
+ 						+ extraBytes
+ 						+ objectMemory newSpaceBytes
+ 						+ (extraBytes > allocationReserve
+ 							ifTrue: [0]
+ 							ifFalse: [allocationReserve])].
  	"allocate interpreter memory"
  	heapBase := objectMemory startOfMemory.
- 	heapSize := dataSize
- 				+ extraBytes
- 				+ objectMemory newSpaceBytes
- 				+ self interpreterAllocationReserveBytes
- 				+ (objectMemory hasSpurMemoryManagerAPI
- 					ifTrue: [headerSize]
- 					ifFalse: [0]).
  	objectMemory
  		setHeapBase: heapBase
  		memoryLimit: heapBase + heapSize
  		endOfMemory: heapBase + dataSize. "bogus for Spur"
  	objectMemory memory: (Bitmap new: objectMemory memoryLimit // 4).
  
  	"read in the image in bulk, then swap the bytes if necessary"
  	f position: headerSize.
  	count := objectMemory readHeapFromImageFile: f dataBytes: dataSize.
  	count ~= dataSize ifTrue: [self halt].
  	]
  		ensure: [f close].
  
  	self ensureImageFormatIsUpToDate: swapBytes.
  
  	bytesToShift := objectMemory memoryBaseForImageRead - oldBaseAddr.  "adjust pointers for zero base address"
  	Utilities
  		informUser: 'Relocating object pointers...'
  		during: [self initializeInterpreter: bytesToShift]!



More information about the Vm-dev mailing list