Skip to content

Composed image format #377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions smalltalksrc/VMMaker/AbstractComposedImageAccess.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
Class {
#name : #AbstractComposedImageAccess,
#superclass : #AbstractImageAccess,
#category : #'VMMaker-ImageFormat'
}

{ #category : #'file operations' }
AbstractComposedImageAccess >> headerFile: imageFileName [

| imageFile |
imageFile := self imageFile: imageFileName.

^ imageFile / 'header.ston'
]

{ #category : #'file operations' }
AbstractComposedImageAccess >> imageFile: imageFileName [

| imageFile |
imageFile := imageFileName asFileReference.
imageFile ensureCreateDirectory.

^ imageFile
]

{ #category : #'file operations' }
AbstractComposedImageAccess >> segmentDataFile: segmentIndex fromFile: imageFile [

| segmentDataFileName |
segmentDataFileName := (self segmentFileNameWithoutExtension: segmentIndex) , '.data'.

^ imageFile / segmentDataFileName
]

{ #category : #'file operations' }
AbstractComposedImageAccess >> segmentDataFile: segmentIndex inImage: imageFileName [

| imageFile |
imageFile := self imageFile: imageFileName.

^ self segmentDataFile: segmentIndex fromFile: imageFile
]

{ #category : #'file operations' }
AbstractComposedImageAccess >> segmentFileNameWithoutExtension: segmentIndex [

^ 'seg' , segmentIndex asString
]

{ #category : #'file operations' }
AbstractComposedImageAccess >> segmentMetadataFile: segmentIndex fromFile: imageFile [

| segmentDataFileName |
segmentDataFileName := (self segmentFileNameWithoutExtension: segmentIndex) , '.ston'.

^ imageFile / segmentDataFileName
]

{ #category : #'file operations' }
AbstractComposedImageAccess >> segmentMetadataFile: segmentIndex inImage: imageFileName [

| imageFile |
imageFile := self imageFile: imageFileName.

^ self segmentMetadataFile: segmentIndex fromFile: imageFile
]
7 changes: 7 additions & 0 deletions smalltalksrc/VMMaker/AbstractFileReference.extension.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Extension { #name : #AbstractFileReference }

{ #category : #'*VMMaker' }
AbstractFileReference >> hasChildrenMatching: patterns [

^ (self childrenMatching: patterns) isNotEmpty
]
141 changes: 141 additions & 0 deletions smalltalksrc/VMMaker/AbstractImageAccess.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,89 @@ AbstractImageAccess class >> newWithMemory: memory andInterpreter: anInterpreter
^ newInstance
]

{ #category : #reading }
AbstractImageAccess >> extractImageVersionFrom: fileVersion into: header [
"Read and verify the image file version number and return true if the the given image file needs to be byte-swapped. As a side effect, position the file stream just after the version number of the image header. This code prints a warning and does a hard-exit if it cannot find a valid version number."
"This code is based on C code by Ian Piumarta."

<inline: false>
| version firstVersion |
<var: #file type: #sqImageFile>
<var: #imageOffset type: #squeakFileOffsetType>
<var: #header type: #'SpurImageHeaderStruct *'>

"check the version number"
version := firstVersion := fileVersion.
(self readableFormat: version) ifTrue: [
header imageFormat: version.
header swapBytes: false.
^ self].

"try with bytes reversed"
(self readableFormat: version byteSwap32)
ifTrue: [
header imageFormat: version byteSwap32.
header swapBytes: true.
^ self].

"hard failure; abort"
self logError: 'Invalid image format: detected version %d, expected version %d'
_: firstVersion
_: self imageFormatVersion.

self ioExitWithErrorCode: 1.

]

{ #category : #segments }
AbstractImageAccess >> finalizeSegmentsRead: totalBytesRead newBase: newBase [

"newBase should point just past the last bridge. all others should have been eliminated."
self assert: newBase - objectMemory getMemoryMap oldSpaceStart = (totalBytesRead
- (segmentManager numSegments * objectMemory bridgeSize)).

"Segments has correct swizzle values, so it can be used to swizzle objects"
segmentManager setCanSwizzle: true.

"set freeOldSpaceStart now for adjustAllOopsBy:"
objectMemory setFreeOldSpaceStart: newBase.

]

{ #category : #reading }
AbstractImageAccess >> imageFormatCompatibilityVersion [
"This VM is backward-compatible with the immediately preceding version."

^objectMemory wordSize = 4 ifTrue: [6504] ifFalse: [68002]
]

{ #category : #reading }
AbstractImageAccess >> imageFormatVersion [
"Return a magic constant that changes when the image format changes.
Since the image reading code uses this to detect byte ordering, one
must avoid version numbers that are invariant under byte reversal."

<doNotGenerate>
self assert: (objectMemory imageFormatVersion anyMask: 16) = objectMemory hasSpurMemoryManagerAPI.
^objectMemory imageFormatVersion
]

{ #category : #reading }
AbstractImageAccess >> initializeInterpreterFromHeader: header withBytes: bytesRead [

| bytesToShift |

bytesRead ~= header dataSize ifTrue: [
interpreter unableToReadImageError ].

interpreter ensureImageFormatIsUpToDate: header swapBytes.

"compute difference between old and new memory base addresses"
bytesToShift := objectMemory getMemoryMap oldSpaceStart - header oldBaseAddr.

interpreter initializeInterpreter: bytesToShift "adjusts all oops to new location"
]

{ #category : #accessing }
AbstractImageAccess >> interpreter [

Expand All @@ -53,13 +136,71 @@ AbstractImageAccess >> interpreter: anObject [
interpreter := anObject
]

{ #category : #reading }
AbstractImageAccess >> loadHeaderToMemory: header [

objectMemory initializeMemoryMap.

objectMemory specialObjectsOop: header initialSpecialObjectsOop.
objectMemory lastHash: header hdrLastHash.

interpreter setImageHeaderFlagsFrom: header headerFlags.
interpreter setExtraVMMemory: header extraVMMemory.

interpreter setNumStackPages: header hdrNumStackPages.

interpreter initializeObjectMemoryWithEdenBytes: header hdrEdenBytes.

header hdrMaxExtSemTabSize ~= 0 ifTrue: [
interpreter setMaxExtSemSizeTo: header hdrMaxExtSemTabSize ].

]

{ #category : #api }
AbstractImageAccess >> loadImageFromFile: imageFile withHeader: header [

"read in the image in bulk, then swap the bytes if necessary"

<var: #f type: #sqImageFile>
<var: #header type: #SpurImageHeaderStruct>
| bytesRead |

bytesRead := self readSegmentsFromImageFile: imageFile header: header.

self initializeInterpreterFromHeader: header withBytes: bytesRead

]

{ #category : #accessing }
AbstractImageAccess >> objectMemory: memory [

<doNotGenerate>
objectMemory := memory
]

{ #category : #segments }
AbstractImageAccess >> prepareSegmentsToRead [

segmentManager clearSegments.
segmentManager allocateOrExtendSegmentInfos
]

{ #category : #segments }
AbstractImageAccess >> readSegmentsFromImageFile: imageFile header: header [

self subclassResponsibility
]

{ #category : #reading }
AbstractImageAccess >> readableFormat: imageVersion [
"Anwer true if images of the given format are readable by this interpreter.
Allows a virtual machine to accept selected older image formats."

^imageVersion = self imageFormatVersion "Float words in platform-order"
or: [objectMemory hasSpurMemoryManagerAPI not "No compatibility version for Spur as yet"
and: [imageVersion = self imageFormatCompatibilityVersion]] "Float words in BigEndian order"
]

{ #category : #accessing }
AbstractImageAccess >> segmentManager: anObject [

Expand Down
34 changes: 4 additions & 30 deletions smalltalksrc/VMMaker/CogVMSimulator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ cos
Class {
#name : #CogVMSimulator,
#superclass : #CoInterpreterPrimitives,
#traits : 'TVMSimulator',
#classTraits : 'TVMSimulator classTrait',
#instVars : [
'parent',
'enableCog',
Expand Down Expand Up @@ -271,8 +273,8 @@ CogVMSimulator >> basicInitialize [
"This will be overriden when calling initializePluginEntries"
mappedPluginEntries := OrderedCollection new.

imageReader := SpurImageReader newWithMemory: objectMemory andInterpreter: self.
imageWriter := SpurImageWriter newWithMemory: objectMemory andInterpreter: self
imageReader := self class imageReaderClass newWithMemory: objectMemory andInterpreter: self.
imageWriter := self class imageWriterClass newWithMemory: objectMemory andInterpreter: self
]

{ #category : #hooks }
Expand Down Expand Up @@ -2140,34 +2142,6 @@ CogVMSimulator >> openAsMorphNoTranscript [
* (1@(1/0.95))) rounded
]

{ #category : #initialization }
CogVMSimulator >> openOn: fileName extraMemory: extraBytes [

"CogVMSimulator new openOn: 'clone.im' extraMemory: 100000"

| f |

"We set the memory manager if it is not already set"
memoryManager ifNil: [
memoryManager := MachineSimulatorMemoryManager new.
objectMemory memoryManager: memoryManager.
memoryManager wordSize: objectMemory wordSize.
].

"open image file and read the header"
(f := self openImageFileNamed: fileName) ifNil: [ ^ self ].

"Set the image name and the first argument; there are
no arguments during simulation unless set explicitly."
systemAttributes
at: 1 put: fileName;
at: 2 put: nil.

[ imageReader readImageFromFile: f StartingAt: 0 ]
ensure: [ f close ].

]

{ #category : #'stack pages' }
CogVMSimulator >> osCogStackPageHeadroom [
"Notional headroom for the simulator. The platform provides this in the real VM."
Expand Down
Loading