VM Maker: VMMaker-dtl.419.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: VMMaker-dtl.419.mcz

commits-2
 
David T. Lewis uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker-dtl.419.mcz

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

Name: VMMaker-dtl.419
Author: dtl
Time: 22 November 2020, 11:52:26.748 am
UUID: 13a52440-38ce-414c-92a9-8a2ba438b91b
Ancestors: VMMaker-dtl.418

Extend image version compatibility.
For Squeak 6 alpha (current trunk):
Remove use of deprecated hideVScrollBarIndefinitely: with possible cosmetic impact on older image versions but otherwise harmless to remove.
Provide a compatibility method to handle the renaming of includesSubString: to includesSubstring:
Handle the removal of CrLfFileStream.
For circa Squeak 3.8:
Use ifNotNilDo: instead of ifNotNil: when passing a block argument.
Use ifNil:ifNotNilDo: instead of ifNil:ifNotNil: when passing a block argument.
Note, early images require Pragmatizer to undo pragma usage

=============== Diff against VMMaker-dtl.418 ===============

Item was changed:
  ----- Method: BalloonEngineBase class>>initialize (in category 'class initialization') -----
  initialize
  "BalloonEngineBase initialize"
  "BalloonEnginePlugin translateDoInlining: true."
  EdgeInitTable := self initializeEdgeInitTable.
  EdgeStepTable := self initializeEdgeStepTable.
  WideLineWidthTable := self initializeWideLineWidthTable.
  WideLineFillTable := self initializeWideLineFillTable.
  FillTable := self initializeFillTable.
 
+ (Smalltalk classNamed: #BalloonEngineConstants) ifNotNilDo:
- (Smalltalk classNamed: #BalloonEngineConstants) ifNotNil:
  [:balloonEngineConstants|
  (balloonEngineConstants classPool anySatisfy: [:classVarValue| classVarValue isNil]) ifTrue:
  [balloonEngineConstants initialize]]!

Item was changed:
  ----- Method: BalloonEngineSimulation>>copyBitsFrom:to:at: (in category 'simulation') -----
  copyBitsFrom: x0 to: x1 at: y
  "Simulate the copyBits primitive"
 
  | bb |
  bbObj isInteger ifTrue:
  ["Create a proxy object to handle BitBlt calls"
  bb := savedBBObj
  ifNil: [BitBltSimulator new
  initialiseModule;
  setInterpreter: interpreterProxy;
  yourself]
+ ifNotNilDo: [savedBBObj].
- ifNotNil: [savedBBObj].
  (bb loadBitBltFrom: bbObj)
  ifTrue: [bbObj := bb]
  ifFalse: [^ self]].
  bbObj copyBitsFrom: x0 to: x1 at: y.
  "
  interpreterProxy showDisplayBits: bbObj destForm
  Left: bb affectedLeft Top: bb affectedTop
  Right: bb affectedRight Bottom: bb affectedBottom.
  "!

Item was changed:
  ----- Method: CCodeGenerator>>addMethodFor:selector: (in category 'utilities') -----
  addMethodFor: aClass selector: selector
  "Add the given method to the code base and answer its translation
  or nil if it shouldn't be translated."
 
  | method tmethod |
  method := aClass compiledMethodAt: selector.
  method requiresConcreteImplementation ifTrue: [abstractDeclarations add: selector].
  method isAbstract ifTrue: [^nil].
  (method pragmaAt: #doNotGenerate) ifNotNil: [^nil].
  "process optional methods by interpreting the argument to the option: pragma as either
  a Cogit class name or a class variable name or a variable name in VMBasicConstants."
+ (method pragmaAt: #option:) ifNotNilDo:
- (method pragmaAt: #option:) ifNotNil:
  [:pragma| | key |
  key := pragma argumentAt: 1.
  "((Cogit withAllSubclasses anySatisfy: [:c| c name = key])
  and: [VMClass getVMMaker cogitClassName ~= key]) ifTrue:
  [^nil]."
+ (aClass bindingOf: key) ifNotNilDo:
- (aClass bindingOf: key) ifNotNil:
  [:binding|
  binding value ifFalse: [^nil]].
+ (VMBasicConstants bindingOf: key) ifNotNilDo:
- (VMBasicConstants bindingOf: key) ifNotNil:
  [:binding|
  binding value ifFalse: [^nil]]].
  tmethod := self compileToTMethodSelector: selector in: aClass.
  tmethod hasDoNotGenerateStatement ifTrue: [^nil].
  self addMethod: tmethod.
  "If the method has a macro then add the macro.  But keep the method
  for analysis purposes (e.g. its variable accesses)."
+ (method pragmaAt: #cmacro:) ifNotNilDo:
- (method pragmaAt: #cmacro:) ifNotNil:
  [:pragma|
  self addMacro: (pragma argumentAt: 1) for: selector].
+ (method propertyValueAt: #cmacro:) ifNotNilDo:
- (method propertyValueAt: #cmacro:) ifNotNil:
  [:macro|
  self addMacro: macro for: selector].
  ^tmethod!

Item was changed:
  ----- Method: CCodeGenerator>>addStructMethodFor:selector: (in category 'utilities') -----
  addStructMethodFor: aClass selector: selector
  "Add the given struct method to the code base and answer its translation
  or nil if it shouldn't be translated."
+ ^(self addMethodFor: aClass selector: selector) ifNotNilDo:
- ^(self addMethodFor: aClass selector: selector) ifNotNil:
  [:tmethod|
  tmethod transformToStructClassMethodFor: self.
  tmethod]!

Item was changed:
  ----- Method: CCodeGenerator>>declToType: (in category 'public') -----
  declToType: decl
  "Extracts the type from a C declaration string"
 
  | strs r |
  decl isNil ifFalse: [
  (decl indexOf: $=) > 0 ifTrue:
  [ strs := (decl copyFrom: 1 to: ((decl indexOf: $=) - 1)) ]
  ifFalse: [ strs := decl ].
  strs := (strs withoutTrailingBlanks) subStrings: ' '.
  strs size == 1 ifTrue: [ ^ strs first ]
  ifFalse:
  [
  | asterisks |
  r := ''.
  strs allButLastDo: [ :s | r := r,s,' ' ].
  "Bit of a hack to get 'type *'"
  asterisks := (strs last copyFrom: 1 to: (strs last lastIndexOf: $*)).
  asterisks size > 0 ifTrue: [ r := r,' ',asterisks ].
  r := r withoutTrailingBlanks.
+ (((r indexOf: $( ) > 0) or: [ (r indexOf: $) ) > 0 ] ) ifTrue: [ ^nil ].
- (((r indexOf: $() > 0) or: ((r indexOf: $)) > 0)) ifTrue: [ ^nil ].
  ^r withoutTrailingBlanks
  ].
  ] ifTrue: [ ^nil ].!

Item was changed:
  ----- Method: CCodeGenerator>>extractTypeFor:fromDeclaration: (in category 'utilities') -----
  extractTypeFor: aVariable fromDeclaration: aVariableDeclaration
  "Eliminate inessentials from aVariableDeclaration to answer a C type without the variable,
  or initializations etc"
  | decl |
  decl := aVariableDeclaration.
  (decl beginsWith: 'static') ifTrue:
  [decl := decl allButFirst: 6].
+ (decl indexOf: $= ifAbsent: []) ifNotNilDo:
- (decl indexOf: $= ifAbsent: []) ifNotNil:
  [:index| decl := decl copyFrom: 1 to: index - 1].
  decl := decl copyReplaceAll: aVariable with: '' tokenish: [:ch| ch = $_ or: [ch isAlphaNumeric]].
  ^self baseTypeForType: decl!

Item was changed:
  ----- Method: CCodeGenerator>>generateIfFalse:on:indent: (in category 'C translation') -----
  generateIfFalse: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
 
  (self nilOrBooleanConstantReceiverOf: msgNode)
  ifNil:
  [aStream nextPutAll: 'if (!!('.
  msgNode receiver emitCCodeAsExpressionOn: aStream level: level + 1 generator: self.
  aStream nextPutAll: ')) {'; cr.
  msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
  level timesRepeat: [aStream tab].
  aStream nextPut: $}]
+ ifNotNilDo:
- ifNotNil:
  [:const |
  const ifFalse:
  [msgNode args first emitCCodeOn: aStream level: level generator: self]]!

Item was changed:
  ----- Method: CCodeGenerator>>generateIfFalseAsArgument:on:indent: (in category 'C translation') -----
  generateIfFalseAsArgument: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
 
  (self nilOrBooleanConstantReceiverOf: msgNode)
  ifNil:
  [aStream nextPutAll: '(!!('.
  msgNode receiver emitCCodeAsArgumentOn: aStream level: 0 generator: self.
  aStream nextPut: $); crtab: level + 1; nextPut: $?; space.
  msgNode args last emitCCodeAsArgumentOn: aStream level: level + 2 generator: self.
  aStream crtab: level + 1; nextPutAll: ': 0)']
+ ifNotNilDo:
- ifNotNil:
  [:const|
  const ifFalse:
  [msgNode args first emitCCodeAsArgumentOn: aStream level: level generator: self]]!

Item was changed:
  ----- Method: CCodeGenerator>>generateIfFalseIfTrue:on:indent: (in category 'C translation') -----
  generateIfFalseIfTrue: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
 
  (self nilOrBooleanConstantReceiverOf: msgNode)
  ifNil:
  [aStream nextPutAll: 'if ('.
  msgNode receiver emitCCodeAsExpressionOn: aStream level: level generator: self.
  aStream nextPutAll: ') {'; cr.
  msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
  aStream tab: level; nextPut: $}; nextPutAll: ' else {'; cr.
  msgNode args first emitCCodeOn: aStream level: level + 1 generator: self.
  aStream tab: level; nextPut: $}]
+ ifNotNilDo:
- ifNotNil:
  [:const |
  (const ifTrue: [msgNode args last] ifFalse: [msgNode args first])
  emitCCodeOn: aStream level: level generator: self]!

Item was changed:
  ----- Method: CCodeGenerator>>generateIfFalseIfTrueAsArgument:on:indent: (in category 'C translation') -----
  generateIfFalseIfTrueAsArgument: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
 
  (self nilOrBooleanConstantReceiverOf: msgNode)
  ifNil:
  [aStream nextPut: $(.
  msgNode receiver emitCCodeAsArgumentOn: aStream level: level generator: self.
  aStream crtab: level + 1; nextPut: $?; space.
  msgNode args last emitCCodeAsArgumentOn: aStream level: level + 2 generator: self.
  aStream crtab: level + 1; nextPut: $:; space.
  msgNode args first emitCCodeAsArgumentOn: aStream level: level + 2 generator: self.
  aStream nextPut: $)]
+ ifNotNilDo:
- ifNotNil:
  [:const|
  (const
  ifTrue: [msgNode args last]
  ifFalse: [msgNode args first])
  emitCCodeAsArgumentOn: aStream level: level generator: self]!

Item was changed:
  ----- Method: CCodeGenerator>>generateIfTrue:on:indent: (in category 'C translation') -----
  generateIfTrue: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
 
  (self nilOrBooleanConstantReceiverOf: msgNode)
  ifNil:
  [aStream nextPutAll: 'if ('.
  msgNode receiver emitCCodeAsExpressionOn: aStream level: level generator: self.
  aStream nextPutAll: ') {'; cr.
  msgNode args first emitCCodeOn: aStream level: level + 1 generator: self.
  level timesRepeat: [ aStream tab ].
  aStream nextPut: $}]
+ ifNotNilDo:
- ifNotNil:
  [:const |
  const ifTrue:
  [msgNode args first emitCCodeOn: aStream level: level generator: self]]!

Item was changed:
  ----- Method: CCodeGenerator>>generateIfTrueAsArgument:on:indent: (in category 'C translation') -----
  generateIfTrueAsArgument: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
 
  (self nilOrBooleanConstantReceiverOf: msgNode)
  ifNil:
  [aStream nextPut: $(.
  msgNode receiver emitCCodeAsArgumentOn: aStream level: level generator: self.
  aStream crtab: level + 1; nextPut: $?; space.
  msgNode args first emitCCodeAsArgumentOn: aStream level: level + 2 generator: self.
  aStream crtab: level + 1; nextPutAll: ': 0)']
+ ifNotNilDo:
- ifNotNil:
  [:const|
  const ifTrue:
  [msgNode args first emitCCodeAsArgumentOn: aStream level: level generator: self]]!

Item was changed:
  ----- Method: CCodeGenerator>>generateIfTrueIfFalse:on:indent: (in category 'C translation') -----
  generateIfTrueIfFalse: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
 
  (self nilOrBooleanConstantReceiverOf: msgNode)
  ifNil:
  [aStream nextPutAll: 'if ('.
  msgNode receiver emitCCodeAsExpressionOn: aStream level: level generator: self.
  aStream nextPutAll: ') {'; cr.
  msgNode args first emitCCodeOn: aStream level: level + 1 generator: self.
  aStream tab: level; nextPut: $}; nextPutAll: ' else {'; cr.
  msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
  aStream tab: level; nextPut: $}]
+ ifNotNilDo:
- ifNotNil:
  [:const |
  (const ifTrue: [msgNode args first] ifFalse: [msgNode args last])
  emitCCodeOn: aStream level: level generator: self]!

Item was changed:
  ----- Method: CCodeGenerator>>generateIfTrueIfFalseAsArgument:on:indent: (in category 'C translation') -----
  generateIfTrueIfFalseAsArgument: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
 
  (self nilOrBooleanConstantReceiverOf: msgNode)
  ifNil:
  [aStream nextPut: $(.
  msgNode receiver emitCCodeAsArgumentOn: aStream level: level generator: self.
  aStream crtab: level + 1; nextPut: $?; space.
  msgNode args first emitCCodeAsArgumentOn: aStream level: level + 2 generator: self.
  aStream crtab: level + 1; nextPut: $:; space.
  msgNode args last emitCCodeAsArgumentOn: aStream level: level + 2 generator: self.
  aStream nextPut: $)]
+ ifNotNilDo:
- ifNotNil:
  [:const|
  (const ifTrue: [msgNode args first] ifFalse: [msgNode args last])
  emitCCodeAsArgumentOn: aStream level: level generator: self]!

Item was changed:
  ----- Method: CCodeGenerator>>generateValue:on:indent: (in category 'C translation') -----
  generateValue: aTSendNode on: aStream indent: level
  "Reduce [:formal ... :formalN| body ] value: actual ... value: actualN
  to body with formals substituted for by actuals."
  | substitution substitutionDict newLabels |
  self assert: aTSendNode receiver isStmtList.
  self assert: aTSendNode receiver args size = aTSendNode args size.
  substitution := aTSendNode receiver copy.
  substitution renameLabelsForInliningInto: currentMethod.
  substitutionDict := Dictionary new: aTSendNode args size * 2.
  aTSendNode receiver args with: aTSendNode args do:
  [ :argName :exprNode |
  substitutionDict at: argName put: exprNode].
  substitution
  bindVariablesIn: substitutionDict;
  emitCCodeOn: aStream level: level generator: self.
  newLabels := Set withAll: currentMethod labels.
  substitution nodesDo:
+ [:node| node isLabel ifTrue: [node label ifNotNilDo: [:label| newLabels add: label]]].
- [:node| node isLabel ifTrue: [node label ifNotNil: [:label| newLabels add: label]]].
  "now add the new labels so that a subsequent inline of
  the same block will be renamed with different labels."
  currentMethod labels: newLabels!

Item was changed:
  ----- Method: CCodeGenerator>>generateValueAsArgument:on:indent: (in category 'C translation') -----
  generateValueAsArgument: aTSendNode on: aStream indent: level
  "Reduce [:formal ... :formalN| body ] value: actual ... value: actualN
  to body with formals substituted for by actuals."
  | substitution substitutionDict newLabels |
  self assert: aTSendNode receiver isStmtList.
  self assert: aTSendNode receiver args size = aTSendNode args size.
  substitution := aTSendNode receiver copy.
  substitution renameLabelsForInliningInto: currentMethod.
  substitutionDict := Dictionary new: aTSendNode args size * 2.
  aTSendNode receiver args with: aTSendNode args do:
  [ :argName :exprNode |
  substitutionDict at: argName put: exprNode].
  substitution
  bindVariablesIn: substitutionDict;
  emitCCodeAsArgumentOn: aStream level: level generator: self.
  newLabels := Set withAll: currentMethod labels.
  substitution nodesDo:
+ [:node| node isLabel ifTrue: [node label ifNotNilDo: [:label| newLabels add: label]]].
- [:node| node isLabel ifTrue: [node label ifNotNil: [:label| newLabels add: label]]].
  "now add the new labels so that a subsequent inline of
  the same block will be renamed with different labels."
  currentMethod labels: newLabels!

Item was changed:
  ----- Method: CCodeGenerator>>storeCodeOnFile:doInlining:doAssertions: (in category 'public') -----
  storeCodeOnFile: fileName doInlining: inlineFlag doAssertions: assertionFlag
  "Store C code for this code base on the given file."
 
  | stream |
+ stream := VMMaker forceNewFileNamed: fileName.
- stream := CrLfFileStream forceNewFileNamed: fileName.
  stream ifNil: [Error signal: 'Could not open C code file: ', fileName].
  self emitCCodeOn: stream doInlining: inlineFlag doAssertions: assertionFlag.
  stream close!

Item was changed:
  ----- Method: CCodeGenerator>>storeHeaderFor:onFile: (in category 'public') -----
  storeHeaderFor: interpreterClassName onFile: fileName
  "Store C header code for this interpreter on the given file."
 
  | aStream |
+ aStream := VMMaker forceNewFileNamed: fileName.
- aStream := CrLfFileStream forceNewFileNamed: fileName.
  aStream ifNil: [Error signal: 'Could not open C header file: ', fileName].
  aStream
  nextPutAll: '/* ';
  nextPutAll: VMMaker headerNotice;
  nextPutAll: ' */'; cr; cr;
  nextPutAll: (self fileHeaderVersionStampForSourceClass: nil); cr; cr;
  nextPutAll: '#ifndef HAVE_INTERP_H'; cr;
  nextPutAll: '# define HAVE_INTERP_H'; cr;
  nextPutAll: '#endif'; cr; cr.
  self emitVmmVersionOn: aStream.
  (Smalltalk classNamed: interpreterClassName)
  emitInterpreterProxyVersionOn: aStream.
  self emitDefineBytesPerWordOn: aStream.
  aStream cr.
  aStream close
  !

Item was changed:
  ----- Method: CCodeGenerator>>var:declareC: (in category 'public') -----
  var: varName declareC: declarationString
  "Record the given C declaration for a global variable."
 
+ (self string: declarationString includesSubstring: varName) ifFalse:
- (declarationString includesSubString: varName) ifFalse:
  [self error: 'declaration omits variable name.  probably an error.  use e.g. var:type:'].
  variableDeclarations at: varName asString put: declarationString.!

Item was changed:
  ----- Method: ContextInterpreter>>primitiveMemorySnapshotBytesWithHeader (in category 'snapshot utility primitives') -----
  primitiveMemorySnapshotBytesWithHeader
  "Primitive. Answer an array with a snapshot copy of the object memory as
  of the point of entry to this primitive, and with the header information for
  the image at the point of the snapshot.
 
  The memory snapshot is a ByteArray copy of the object memory, and the header
  information is an array of the values that would be stored in an image file
  header if the image was being saved to disk. The header state information
  along with memory snapshot are sufficient to initialize an an image to be run
  in an interpreter."
 
- <export: true>
  "pop rcvr. A resuming image will see this primitive answering true, otherwise
  it will answer the expected value of a two element array. Test for result equal
  to true to determine if the image is being resumed from a saved snapshot.."
  | result |
+ <export: true>
  self pop: argumentCount + 1.
  self push: objectMemory getTrueObj. "resuming image will see this"
  result := self
  headerAndSnapshotOfSize: self prepareForSnapshot
  class: objectMemory classByteArray.
  self pop: 1. "restore stack"
  self push: result. "normal sender will see this"
  !

Item was changed:
  ----- Method: ContextInterpreter>>primitiveMemorySnapshotWithHeader (in category 'snapshot utility primitives') -----
  primitiveMemorySnapshotWithHeader
  "Primitive. Answer an array with a snapshot copy of the object memory as
  of the point of entry to this primitive, and with the header information for
  the image at the point of the snapshot.
 
  The memory snapshot is a Bitmap copy of the object memory, and the header
  information is an array of the values that would be stored in an image file
  header if the image was being saved to disk. The header state information
  along with memory snapshot are sufficient to initialize an an image to be run
  in an interpreter."
 
- <export: true>
  "pop rcvr. A resuming image will see this primitive answering true, otherwise
  it will answer the expected value of a two element array. Test for result equal
  to true to determine if the image is being resumed from a saved snapshot.."
  | result |
+ <export: true>
  self pop: argumentCount + 1.
+ self push: objectMemory getTrueObj. "resuming image will see this"
- self push: objectMemory getTrueObj. "resuming image will see this"
  result := self
  headerAndSnapshotOfSize: self prepareForSnapshot
  class: objectMemory classBitmap.
  self pop: 1. "restore stack"
  self push: result. "normal sender will see this"
  !

Item was changed:
  ----- Method: ContextInterpreter>>primitiveResumeFromSnapshot (in category 'snapshot utility primitives') -----
  primitiveResumeFromSnapshot
  "Discard the current object memory and resume interpreter execution
  in the provided snapshot."
 
- <export: true>
  | expectedArraySize snapshotValues size newMemoryBytesOrBitmap bigEndian snapshotImageFormat snapshotStartOfMemory snapshotSpecialObjectsOop snapshotLastHash screenSizePoint headerSize imageBytes imageHeaderFlags snapshotExtraVMMemory swapBytes snapshotFullScreen defaultHeapSize desiredHeapSize |
+ <export: true>
  expectedArraySize := 11. "ImageSnapshot new asValues size => 11"
  argumentCount == 1
  ifFalse: [ ^self primitiveFailFor: PrimErrBadNumArgs].
  snapshotValues := self stackObjectValue: 0.
  self assertClassOf: snapshotValues is: (objectMemory splObj: ClassArray).
  self successful
  ifFalse: [ ^self primitiveFailFor: PrimErrBadArgument].
  size := objectMemory numSlotsOf: snapshotValues.
  size < expectedArraySize ifTrue: [ ^self primitiveFailFor: PrimErrBadArgument].
  newMemoryBytesOrBitmap := objectMemory fetchPointer: 0 ofObject: snapshotValues.
  bigEndian := (objectMemory fetchPointer: 1 ofObject: snapshotValues) = objectMemory trueObject.
  snapshotImageFormat := objectMemory integerValueOf: (objectMemory fetchPointer: 2 ofObject: snapshotValues)..
  (self readableFormat: snapshotImageFormat)
  ifFalse: [ ^self primitiveFailFor: PrimErrInappropriate ].
  headerSize := objectMemory integerValueOf: (objectMemory fetchPointer: 3 ofObject: snapshotValues)..
  imageBytes := self positive32BitValueOf: (objectMemory fetchPointer: 4 ofObject: snapshotValues).. "good for up to 2GB image"
  snapshotStartOfMemory := objectMemory integerValueOf: (objectMemory fetchPointer: 5 ofObject: snapshotValues)..
  snapshotSpecialObjectsOop := objectMemory integerValueOf: (objectMemory fetchPointer: 6 ofObject: snapshotValues)..
  snapshotLastHash := objectMemory integerValueOf: (objectMemory fetchPointer: 7 ofObject: snapshotValues)..
  screenSizePoint := objectMemory fetchPointer: 8 ofObject: snapshotValues..
  self assertClassOf: screenSizePoint is: (objectMemory splObj: ClassPoint).
  self successful
  ifFalse: [ ^self primitiveFailFor: PrimErrBadArgument].
  imageHeaderFlags := objectMemory integerValueOf: (objectMemory fetchPointer: 9 ofObject: snapshotValues)..
  snapshotExtraVMMemory := objectMemory integerValueOf: (objectMemory fetchPointer: 10 ofObject: snapshotValues)..
 
  swapBytes := bigEndian ~= self isBigEnder.
  snapshotFullScreen := false. "FIXME"
 
  "From sqUnixMain.c
  #define DefaultHeapSize           20
  megabytes BEYOND actual image size"
  defaultHeapSize := 20 * 1000 * 1000.
  desiredHeapSize := defaultHeapSize + imageBytes.
 
  self
  snapshotResume: newMemoryBytesOrBitmap
  heapSize: desiredHeapSize
  swapBytes: swapBytes
  oldBaseAddr: snapshotStartOfMemory
  specialObjectsOop: snapshotSpecialObjectsOop
  lastHash: snapshotLastHash
  savedWindowSize: screenSizePoint
  fullScreenFlag: snapshotFullScreen
  extraVMMemory: snapshotExtraVMMemory.
 
  self pop: 1 thenPush: newMemoryBytesOrBitmap.
 
  !

Item was changed:
  ----- Method: InterpreterPlugin class>>storeString:onFileNamed: (in category 'translation') -----
  storeString: s onFileNamed: fileName
  "Store the given string in a file of the given name."
 
  | f |
+ f := VMMaker forceNewFileNamed: fileName.
- f := CrLfFileStream forceNewFileNamed: fileName.
  f nextPutAll: s.
  f close.!

Item was changed:
  ----- Method: NewObjectMemorySimulator>>lookupAddress: (in category 'memory access') -----
  lookupAddress: address
  "If address appears to be that of a Symbol or a few well-known objects (such as classes) answer it, otherwise answer nil.
  For code disassembly"
  <doNotGenerate>
  | fmt size string class classSize maybeThisClass classNameIndex thisClassIndex |
  (self addressCouldBeObj: address) ifFalse:
  [^nil].
  fmt := self formatOf: address.
  size := self lengthOf: address baseHeader: (self baseHeader: address) format: fmt.
  size = 0 ifTrue:
  [^address caseOf: { [nilObj] -> ['nil']. [trueObj] -> ['true']. [falseObj] -> ['false'] } otherwise: []].
  ((fmt between: 8 and: 11) "indexable byte fields"
  and: [(size between: 1 and: 64)
  and: [Scanner isLiteralSymbol: (string := (0 to: size - 1) collect: [:i| Character value: (self fetchByte: i ofObject: address)])]]) ifTrue:
  [^'#', (ByteString withAll: string)].
  class := self fetchClassOfNonInt: address.
  ((self addressCouldBeObj: class)
  and: [(self headerType: class) ~= HeaderTypeShort]) ifFalse:
  [^nil].
  "address is either a class or a metaclass, or an instance of a class or invalid.  determine which."
  classNameIndex := coInterpreter classNameIndex.
  thisClassIndex := coInterpreter thisClassIndex.
  ((classSize := self lengthOf: class baseHeader: (self baseHeader: address) format: fmt) <= (classNameIndex max: thisClassIndex)
  or: [classSize > 255]) ifTrue:
  [^nil].
  "Address could be a class or a metaclass"
  (fmt = 1 and: [size >= classNameIndex]) ifTrue:
  ["Is address a class? If so class's thisClass is address."
+ (self lookupAddress: (self fetchPointer: classNameIndex ofObject: address)) ifNotNilDo:
- (self lookupAddress: (self fetchPointer: classNameIndex ofObject: address)) ifNotNil:
  [:maybeClassName|
  (self fetchPointer: thisClassIndex ofObject: class) = address ifTrue:
  [^maybeClassName allButFirst]].
  "Is address a Metaclass?  If so class's name is Metaclass and address's thisClass holds the class name"
  ((self isBytes: (self fetchPointer: classNameIndex ofObject: class))
  and: [(self lookupAddress: (self fetchPointer: classNameIndex ofObject: class)) = '#Metaclass'
  and: [size >= thisClassIndex]]) ifTrue:
  [maybeThisClass := self fetchPointer: thisClassIndex ofObject: address.
  (self lookupAddress: (self fetchPointer: classNameIndex ofObject: maybeThisClass)) ifNotNil:
  [:maybeThisClassName| ^maybeThisClassName allButFirst, ' class']]].
  ^(self lookupAddress: (self fetchPointer: classNameIndex ofObject: class)) ifNotNil:
  [:maybeClassName| 'a(n) ', maybeClassName allButFirst]!

Item was added:
+ ----- Method: Object>>string:includesSubstring: (in category '*VMMaker-translation support') -----
+ string: aString includesSubstring: substring
+ "Backward compatibility for a method that was renamed but needs to
+ remain functional for VMMaker across a range of images."
+
+ ^ (aString respondsTo: #includesSubstring: )
+ ifTrue: [aString perform: #includesSubstring: with: substring]
+ ifFalse: [aString perform: #includesSubString: with: substring]
+ !

Item was changed:
  ----- Method: SlangTest>>testInterpDeclareStatic (in category 'testing interpreter') -----
  testInterpDeclareStatic
  "A static directive should cause the generated function to be declared static."
 
  | stssi m1 p1 m2 p2 |
  stssi := SlangTestSupportInterpreter inline: false.
  m1 := (stssi asCString: #declareStaticTrueByMethod)
  copyReplaceAll: 'declareStaticTrueByMethod'
  with: 'methodName'.
  p1 := (stssi asCString: #declareStaticTrueByPragma)
  copyReplaceAll: 'declareStaticTrueByPragma'
  with: 'methodName'.
  self assert: m1 = p1.
 
  m2 := (stssi asCString: #declareStaticFalseByMethod)
  copyReplaceAll: 'declareStaticFalseByMethod'
  with: 'methodName'.
  p2 := (stssi asCString: #declareStaticFalseByPragma)
  copyReplaceAll: 'declareStaticFalseByPragma'
  with: 'methodName'.
  self assert: m2 = p2.
 
  "verify that the keyword 'static appears in the generated C source"
+ self assert: (self string: m1 includesSubstring: 'static').
+ self assert: (self string: p1 includesSubstring: 'static').
+ self deny: (self string: m2 includesSubstring: 'static').
+ self deny: (self string: p2 includesSubstring: 'static')
- self assert: (m1 includesSubString: 'static').
- self assert: (p1 includesSubString: 'static').
- self deny: (m2 includesSubString: 'static').
- self deny: (p2 includesSubString: 'static')
  !

Item was changed:
  ----- Method: SlangTest>>testInterpDoNotdoNotGenerateByMethod (in category 'testing interpreter') -----
  testInterpDoNotdoNotGenerateByMethod
  "A doNotdoNotGenerate statement should prevent code generation"
 
  "(SlangTest selector: #testInterpDoNotdoNotGenerateByMethod) debug"
 
  | stssi m |
  stssi := SlangTestSupportInterpreter inline: false.
  self assert: (SlangTestSupportInterpreter canUnderstand: #doNotGenerateByMethod).
  m := stssi asCString: #doNotGenerateByMethod.
+ self assert: (self string: m includesSubstring: 'No source has been generated').
+ self deny: (self string: stssi asCString includesSubstring: 'doNotGenerateByMethod').
- self assert: (m includesSubString: 'No source has been generated').
- self deny: (stssi asCString includesSubString: 'doNotGenerateByMethod').
  self assert: (stssi doNotGenerateByMethod = 4)
 
  !

Item was changed:
  ----- Method: SlangTest>>testInterpDoNotdoNotGenerateByPragma (in category 'testing interpreter') -----
  testInterpDoNotdoNotGenerateByPragma
  "A <doNotdoNotGenerate> declaration should prevent code generation"
 
  | stssi m |
  stssi := SlangTestSupportInterpreter inline: false.
  self assert: (SlangTestSupportInterpreter canUnderstand: #doNotGenerateByPragma).
  m := stssi asCString: #doNotGenerateByPragma.
+ self assert: (self string: m includesSubstring: 'No source has been generated').
+ self deny: (self string: stssi asCString includesSubstring: 'doNotGenerateByPragma').
- self assert: (m includesSubString: 'No source has been generated').
- self deny: (stssi asCString includesSubString: 'doNotGenerateByPragma').
  self assert: (stssi doNotGenerateByPragma = 4)
  !

Item was changed:
  ----- Method: SlangTest>>testInterpDoNotdoNotGenerateSubclassResponsibility (in category 'testing interpreter') -----
  testInterpDoNotdoNotGenerateSubclassResponsibility
  "If a method contains self subclassResponsibility, assume it is not meant for translation."
 
  | stssi m |
  stssi := SlangTestSupportInterpreter inline: false.
  self assert: (SlangTestSupportInterpreter canUnderstand: #anAbstractMethod).
  m := stssi asCString: #anAbstractMethod.
+ self assert: (self string: m includesSubstring: 'No source has been generated').
+ self deny: (self string: stssi asCString includesSubstring: 'anAbstractMethod').
- self assert: (m includesSubString: 'No source has been generated').
- self deny: (stssi asCString includesSubString: 'anAbstractMethod').
  self should: [stssi anAbstractMethod]
  raise: Error
 
  !

Item was changed:
  ----- Method: SlangTest>>testInterpMixedMethodAndPragmaDeclarations (in category 'testing interpreter') -----
  testInterpMixedMethodAndPragmaDeclarations
  "Pragmas and method declarations should coexist"
 
  | stssi s |
  stssi := SlangTestSupportInterpreter inline: false.
  s := (stssi asCString: #varDefByMethodAndPragma)
  copyReplaceAll: 'varDefByMethod'
  with: 'methodName'.
+ self assert: (self string: s includesSubstring: 'unsigned int * bar').
+ self assert: (self string: s includesSubstring: 'char *foo').
+ self assert: (self string: s includesSubstring: 'float baz').
+ self assert: (self string: s includesSubstring: 'double fum').
- self assert: (s includesSubString: 'unsigned int * bar').
- self assert: (s includesSubString: 'char *foo').
- self assert: (s includesSubString: 'float baz').
- self assert: (s includesSubString: 'double fum').
  !

Item was changed:
  ----- Method: SlangTest>>testIvarShouldNotBeRedeclaredAsLocal (in category 'testing variable declaration') -----
  testIvarShouldNotBeRedeclaredAsLocal
  "Document a bug in some versions of the code generator. If an instance variable is
  referenced in the generated code, that variable should not be declared as a local
  in the function."
 
  | stssi s |
  stssi := SlangTestSupportInterpreter inline: false.
  s := stssi asCString: #setBreakSelector: .
+ self deny: (self string: s includesSubstring: 'sqInt breakSelector;')
- self deny: (s includesSubString: 'sqInt breakSelector;')
  !

Item was changed:
  ----- Method: SlangTest>>testLiteralName (in category 'testing variable declaration') -----
  testLiteralName
  "sizeOf: #Foo should translated to C function call sizeof(Foo), where Foo is a literal, not a string"
 
  | stssi s |
  stssi := SlangTestSupportInterpreter inline: false.
  s := stssi asCString: #sizeOfFoo .
+ self assert: (self string: s includesSubstring: 'sizeOf(Foo)').
+ self deny: (self string: s includesSubstring: 'sizeOf("Foo")').
- self assert: (s includesSubString: 'sizeOf(Foo)').
- self deny: (s includesSubString: 'sizeOf("Foo")').
 
  !

Item was changed:
  ----- Method: SlangTest>>testLocalizeGlobalVariables (in category 'testing variable declaration') -----
  testLocalizeGlobalVariables
  "CCodeGenerator>>localizeGlobalVariables performs an optimization
  that may be misleading when introducing a new method. This test
  documents that optimization.
 
  If a method makes reference to an instance variable, and if this is the
  only method containing a reference to that variable, then the C translator
  will produce a local variable declaration in the generated function, and no
  global declaration will appear in the generated source file. This optimization
  is applied after inlining has been performed, so there are legitimate cases
  where a variable must be an instance variable referenced by two methods,
  but can be made local if those methods are inlined into a single method
  and only one method reference to the variable remains. See
  ObjectMemory>>markAndSweep: for an example."
 
  | stssi s |
  stssi := SlangTestSupportInterpreter inline: false.
  s := stssi asCString: #methodWithReferenceToVariables .
  "variable with one method reference is promoted to a local method variable"
+ self assert: (self string: s includesSubstring: 'sqInt aVarWithOneReference;').
- self assert: (s includesSubString: 'sqInt aVarWithOneReference;').
  "normal expected behavior, the variable is global in the generated source module."
+ self deny: (self string: s includesSubstring: 'sqInt aVarWithTwoReferences;')
- self deny: (s includesSubString: 'sqInt aVarWithTwoReferences;')
  !

Item was changed:
  ----- Method: SlangTest>>testPluginDeclareStatic (in category 'testing base plugins') -----
  testPluginDeclareStatic
  "A static directive should cause the generated function to be declared static."
 
  | stsp m1 p1 m2 p2 |
  stsp := SlangTestSupportPlugin inline: false.
  m1 := (stsp asCString: #declareStaticTrueByMethod)
  copyReplaceAll: 'declareStaticTrueByMethod'
  with: 'methodName'.
  p1 := (stsp asCString: #declareStaticTrueByPragma)
  copyReplaceAll: 'declareStaticTrueByPragma'
  with: 'methodName'.
  self assert: m1 = p1.
 
  m2 := (stsp asCString: #declareStaticFalseByMethod)
  copyReplaceAll: 'declareStaticFalseByMethod'
  with: 'methodName'.
  p2 := (stsp asCString: #declareStaticFalseByPragma)
  copyReplaceAll: 'declareStaticFalseByPragma'
  with: 'methodName'.
  self assert: m2 = p2.
 
  "verify that the keyword 'static appears in the generated C source"
+ self assert: (self string: m1 includesSubstring: 'static').
+ self assert: (self string: p1 includesSubstring: 'static').
+ self deny: (self string: m2 includesSubstring: 'static').
+ self deny: (self string: p2 includesSubstring: 'static')
- self assert: (m1 includesSubString: 'static').
- self assert: (p1 includesSubString: 'static').
- self deny: (m2 includesSubString: 'static').
- self deny: (p2 includesSubString: 'static')
  !

Item was changed:
  ----- Method: SlangTest>>testPluginDoNotGenerateByMethod (in category 'testing base plugins') -----
  testPluginDoNotGenerateByMethod
  "A doNotdoNotGenerate statement should prevent code generation"
 
  | stsp m |
  stsp := SlangTestSupportPlugin inline: false.
  self assert: (SlangTestSupportPlugin canUnderstand: #doNotGenerateByMethod).
  m := stsp asCString: #doNotGenerateByMethod.
+ self assert: (self string: m includesSubstring: 'No source has been generated').
+ self deny: (self string: stsp asCString includesSubstring: 'doNotGenerateByMethod').
- self assert: (m includesSubString: 'No source has been generated').
- self deny: (stsp asCString includesSubString: 'doNotGenerateByMethod').
  self assert: (stsp doNotGenerateByMethod = 4)
  !

Item was changed:
  ----- Method: SlangTest>>testPluginDoNotGenerateByPragma (in category 'testing base plugins') -----
  testPluginDoNotGenerateByPragma
  "A <doNotdoNotGenerate> declaration should prevent code generation"
 
  | stsp m |
  stsp := SlangTestSupportPlugin inline: false.
  self assert: (SlangTestSupportPlugin canUnderstand: #doNotGenerateByPragma).
  m := stsp asCString: #doNotGenerateByPragma.
+ self assert: (self string: m includesSubstring: 'No source has been generated').
+ self deny: (self string: stsp asCString includesSubstring: 'doNotGenerateByPragma').
- self assert: (m includesSubString: 'No source has been generated').
- self deny: (stsp asCString includesSubString: 'doNotGenerateByPragma').
  self assert: (stsp doNotGenerateByPragma = 4)
  !

Item was changed:
  ----- Method: SlangTest>>testPluginDoNotGenerateSubclassResponsibility (in category 'testing base plugins') -----
  testPluginDoNotGenerateSubclassResponsibility
  "If a method contains self subclassResponsibility, assume it is not meant for translation."
 
  | stsp m |
  stsp := SlangTestSupportPlugin inline: false.
  self assert: (SlangTestSupportPlugin canUnderstand: #anAbstractMethod).
  m := stsp asCString: #anAbstractMethod.
+ self assert: (self string: m includesSubstring: 'No source has been generated').
+ self deny: (self string: stsp asCString includesSubstring: 'anAbstractMethod').
- self assert: (m includesSubString: 'No source has been generated').
- self deny: (stsp asCString includesSubString: 'anAbstractMethod').
  self should: [stsp anAbstractMethod]
  raise: Error
  !

Item was changed:
  ----- Method: SlangTest>>testPluginMixedMethodAndPragmaDeclarations (in category 'testing base plugins') -----
  testPluginMixedMethodAndPragmaDeclarations
  "Pragmas and method declarations should coexist"
 
  | stsp s |
  stsp := SlangTestSupportPlugin inline: false.
  s := (stsp asCString: #varDefByMethodAndPragma)
  copyReplaceAll: 'varDefByMethod'
  with: 'methodName'.
+ self assert: (self string: s includesSubstring: 'unsigned int * bar').
+ self assert: (self string: s includesSubstring: 'char *foo').
+ self assert: (self string: s includesSubstring: 'float baz').
+ self assert: (self string: s includesSubstring: 'double fum').
- self assert: (s includesSubString: 'unsigned int * bar').
- self assert: (s includesSubString: 'char *foo').
- self assert: (s includesSubString: 'float baz').
- self assert: (s includesSubString: 'double fum').
  !

Item was changed:
  ----- Method: SlangTest>>testSSIPDeclareStatic (in category 'testing ssip plugins') -----
  testSSIPDeclareStatic
  "A static directive should cause the generated function to be declared static."
 
  | stss m1 p1 m2 p2 |
  stss := SlangTestSupportSSIP inline: false.
  m1 := (stss asCString: #declareStaticTrueByMethod)
  copyReplaceAll: 'declareStaticTrueByMethod'
  with: 'methodName'.
  p1 := (stss asCString: #declareStaticTrueByPragma)
  copyReplaceAll: 'declareStaticTrueByPragma'
  with: 'methodName'.
  self assert: m1 = p1.
 
  m2 := (stss asCString: #declareStaticFalseByMethod)
  copyReplaceAll: 'declareStaticFalseByMethod'
  with: 'methodName'.
  p2 := (stss asCString: #declareStaticFalseByPragma)
  copyReplaceAll: 'declareStaticFalseByPragma'
  with: 'methodName'.
  self assert: m2 = p2.
 
  "verify that the keyword 'static appears in the generated C source"
+ self assert: (self string: m1 includesSubstring: 'static').
+ self assert: (self string: p1 includesSubstring: 'static').
+ self deny: (self string: m2 includesSubstring: 'static').
+ self deny: (self string: p2 includesSubstring: 'static')
- self assert: (m1 includesSubString: 'static').
- self assert: (p1 includesSubString: 'static').
- self deny: (m2 includesSubString: 'static').
- self deny: (p2 includesSubString: 'static')
  !

Item was changed:
  ----- Method: SlangTest>>testSSIPDoNotGenerateByMethod (in category 'testing ssip plugins') -----
  testSSIPDoNotGenerateByMethod
  "A doNotdoNotGenerate statement should prevent code generation"
 
  | stss m |
  stss := SlangTestSupportSSIP inline: false.
  self assert: (SlangTestSupportSSIP canUnderstand: #doNotGenerateByMethod).
  m := stss asCString: #doNotGenerateByMethod.
+ self assert: (self string: m includesSubstring: 'No source has been generated').
+ self deny: (self string: stss asCString includesSubstring: 'doNotGenerateByMethod').
- self assert: (m includesSubString: 'No source has been generated').
- self deny: (stss asCString includesSubString: 'doNotGenerateByMethod').
  self assert: (stss doNotGenerateByMethod = 4)!

Item was changed:
  ----- Method: SlangTest>>testSSIPDoNotGenerateByPragma (in category 'testing ssip plugins') -----
  testSSIPDoNotGenerateByPragma
  "A <doNotdoNotGenerate> declaration should prevent code generation"
 
  | stss m |
  stss := SlangTestSupportSSIP inline: false.
  self assert: (SlangTestSupportSSIP canUnderstand: #doNotGenerateByPragma).
  m := stss asCString: #doNotGenerateByPragma.
+ self assert: (self string: m includesSubstring: 'No source has been generated').
+ self deny: (self string: stss asCString includesSubstring: 'doNotGenerateByPragma').
- self assert: (m includesSubString: 'No source has been generated').
- self deny: (stss asCString includesSubString: 'doNotGenerateByPragma').
  self assert: (stss doNotGenerateByPragma = 4)
  !

Item was changed:
  ----- Method: SlangTest>>testSSIPDoNotGenerateSubclassResponsibility (in category 'testing ssip plugins') -----
  testSSIPDoNotGenerateSubclassResponsibility
  "If a method contains self subclassResponsibility, assume it is not meant for translation."
 
  | stss m |
  stss := SlangTestSupportSSIP inline: false.
  self assert: (SlangTestSupportSSIP canUnderstand: #anAbstractMethod).
  m := stss asCString: #anAbstractMethod.
+ self assert: (self string: m includesSubstring: 'No source has been generated').
+ self deny: (self string: stss asCString includesSubstring: 'anAbstractMethod').
- self assert: (m includesSubString: 'No source has been generated').
- self deny: (stss asCString includesSubString: 'anAbstractMethod').
  self should: [stss anAbstractMethod]
  raise: Error
  !

Item was changed:
  ----- Method: SlangTest>>testSSIPMixedMethodAndPragmaDeclarations (in category 'testing ssip plugins') -----
  testSSIPMixedMethodAndPragmaDeclarations
  "Pragmas and method declarations should coexist"
 
  | stss s |
  stss := SlangTestSupportSSIP inline: false.
  s := (stss asCString: #varDefByMethodAndPragma)
  copyReplaceAll: 'varDefByMethod'
  with: 'methodName'.
+ self assert: (self string: s includesSubstring: 'unsigned int * bar').
+ self assert: (self string: s includesSubstring: 'char *foo').
+ self assert: (self string: s includesSubstring: 'float baz').
+ self assert: (self string: s includesSubstring: 'double fum').
- self assert: (s includesSubString: 'unsigned int * bar').
- self assert: (s includesSubString: 'char *foo').
- self assert: (s includesSubString: 'float baz').
- self assert: (s includesSubString: 'double fum').
  !

Item was changed:
  ----- Method: SlangTest>>testSetInstanceVariableWithAnAccessorMethod (in category 'testing intermediate variable removal') -----
  testSetInstanceVariableWithAnAccessorMethod
  "Intermediate variable from parameter of accessor method should be removed.
  This is an existing limitation of the inliner, and could be improved for better code
  generation. It is not a bug."
 
  | stssi s |
  stssi := SlangTestSupportInterpreter inline: true.
  s := (stssi asCString: #setInstanceVariableWithAnAccessorMethod)
  copyReplaceAll: 'setInstanceVariableWithAnAccessorMethod'
  with: 'methodName'.
+ self deny: (self string: s includesSubstring: 'sqInt oop').
+ self assert: (self string: s includesSubstring: 'aVariable = remap(').
- self deny: (s includesSubString: 'sqInt oop').
- self assert: (s includesSubString: 'aVariable = remap(').
 
  "Should be translated to something similar to this:
  aVariable = remap(objectMemory, nilObj);
 
  Not like this:
  oop = remap(objectMemory, nilObj);
  aVariable = oop;"
  !

Item was changed:
  ----- Method: SmartSyntaxPluginSimulator>>computeSignatureFor:from: (in category 'initialize') -----
  computeSignatureFor: selector from: tuple
  | signature |
  self assert: tuple first == #forMap.
  signature := tuple third collect:
  [:className|
  (Smalltalk classNamed: className)
  ifNil: [self error: 'Argument class' , className, ' does not exist']
+ ifNotNilDo:
- ifNotNil:
  [:argClass|
  argClass
  ccg: self
  prolog: true
  expr: [interpreterProxy primitiveFail]
  index: nil]].
  ^signatureMap
  at: tuple second asSymbol
  put: { selector.
  signature.
  tuple fourth
  ifNil: [[:oop| oop]]
+ ifNotNilDo:
- ifNotNil:
  [:rcvrClassSymbol|
  (Smalltalk classNamed: rcvrClassSymbol)
  ifNil: [self error: 'Receiver class' , rcvrClassSymbol, ' does not exist']
+ ifNotNilDo:
- ifNotNil:
  [:rcvrClass|
  rcvrClass
  ccg: self
  prolog: false
  expr: [interpreterProxy primitiveFail]
  index: nil]] }!

Item was changed:
  ----- Method: SmartSyntaxPluginSimulator>>computeSignatureMap (in category 'initialize') -----
  computeSignatureMap
  forMap := true. "true only while we compute the signatureMap"
  signatureMap := Dictionary new.
  actualPlugin class selectorsAndMethodsDo:
  [:s :m|
  (m messages includesAnyOf: #(primitive:parameters: primitive:parameters:receiver:))
  ifTrue: [self getPrimitiveSignatureFor: s]
  ifFalse:
+ [(m pragmaAt: #export:) ifNotNilDo:
- [(m pragmaAt: #export:) ifNotNil:
  [:exportPragma|
  (exportPragma argumentAt: 1) ifTrue:
  [self computeSignatureFor: s from: { #forMap. s. #(). nil }]]]].
  forMap := false!

Item was changed:
  ----- Method: StackInterpreter class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: aCCodeGenerator
  self class == thisContext methodClass ifFalse: [^self]. "Don't duplicate decls in subclasses"
  aCCodeGenerator
  addHeaderFile:'<stddef.h> /* for e.g. alloca */';
  addHeaderFile:'<setjmp.h>';
  addHeaderFile:'"vmCallback.h"'.
  self declareInterpreterVersionIn: aCCodeGenerator
  defaultName: 'Stack'.
  aCCodeGenerator
  var: #interpreterProxy  type: #'struct VirtualMachine*'.
  aCCodeGenerator
  declareVar: #sendTrace type: 'volatile int';
  declareVar: #byteCount type: 'unsigned long'.
  "These need to be pointers or unsigned."
  self declareC: #(instructionPointer method newMethod)
  as: #usqInt
  in: aCCodeGenerator.
  "These are all pointers; char * because Slang has no support for C pointer arithmetic."
  self declareC: #(localIP localSP localFP stackPointer framePointer stackLimit stackMemory)
  as: #'char *'
  in: aCCodeGenerator.
  self declareC: #(stackPage overflowedPage)
  as: #'StackPage *'
  in: aCCodeGenerator.
  aCCodeGenerator removeVariable: 'stackPages'.  "this is an implicit receiver in the translated code."
  aCCodeGenerator
  var: #methodCache
  declareC: 'long methodCache[MethodCacheSize + 1 /* ', (MethodCacheSize + 1) printString, ' */]'.
  aCCodeGenerator
  var: #atCache
  declareC: 'sqInt atCache[AtCacheTotalSize + 1 /* ', (AtCacheTotalSize + 1) printString, ' */]'.
  self primitiveTable do:
  [:symbolOrNot|
  (symbolOrNot isSymbol
  and: [symbolOrNot ~~ #primitiveFail]) ifTrue:
+ [(aCCodeGenerator methodNamed: symbolOrNot) ifNotNilDo:
- [(aCCodeGenerator methodNamed: symbolOrNot) ifNotNil:
  [:tMethod| tMethod returnType: #void]]].
  aCCodeGenerator
  var: #primitiveFunctionPointer
  declareC: 'void (*primitiveFunctionPointer)()'.
  aCCodeGenerator var: #showSurfaceFn type: #'void *'.
  aCCodeGenerator
  var: #jmpBuf
  declareC: 'jmp_buf jmpBuf[MaxJumpBuf + 1 /* ', (MaxJumpBuf + 1) printString, ' */]'.
  aCCodeGenerator
  var: #suspendedCallbacks
  declareC: 'usqInt suspendedCallbacks[MaxJumpBuf + 1 /* ', (MaxJumpBuf + 1) printString, ' */]'.
  aCCodeGenerator
  var: #suspendedMethods
  declareC: 'usqInt suspendedMethods[MaxJumpBuf + 1 /* ', (MaxJumpBuf + 1) printString, ' */]'.
  aCCodeGenerator
  var: #interruptCheckChain
  declareC: 'void (*interruptCheckChain)(void) = 0'.
  aCCodeGenerator
  var: #breakSelector type: #'char *';
  var: #breakSelectorLength
  declareC: 'sqInt breakSelectorLength = -1'.
 
  self declareC: #(nextPollUsecs nextWakeupUsecs longRunningPrimitiveGCUsecs
  longRunningPrimitiveStartUsecs longRunningPrimitiveStopUsecs)
  as: #usqLong
  in: aCCodeGenerator.
  aCCodeGenerator var: #nextProfileTick type: #sqLong.
 
  aCCodeGenerator var: #primitiveTable declareC: 'void (*primitiveTable[' , (MaxPrimitiveIndex + 2) printString , '] )(void)= ' , self primitiveTableString.
  aCCodeGenerator var: #externalPrimitiveTable declareC: 'void (*externalPrimitiveTable[' , (MaxExternalPrimitiveTableSize + 1) printString , '])(void)'.
  !

Item was changed:
  ----- Method: StackInterpreter class>>table:from: (in category 'initialization') -----
  table: anArray from: specArray
  "SpecArray is an array of one of (index selector) or (index1
  index2 selector) or (index nil) or (index1 index2 nil).  If selector
  then the entry is the selector, but if nil the entry is the index."
  | contiguous |
  contiguous := 0.
  specArray do:
  [:spec |
  (spec at: 1) = contiguous ifFalse:
  [self error: 'Non-contiguous table entry'].
  spec size = 2
  ifTrue:
  [anArray
  at: (spec at: 1) + 1
+ put: ((spec at: 2) ifNil: [spec at: 1] ifNotNilDo: [:sym| sym]).
- put: ((spec at: 2) ifNil: [spec at: 1] ifNotNil: [:sym| sym]).
  contiguous := contiguous + 1]
  ifFalse:
  [(spec at: 1) to: (spec at: 2) do:
+ [:i | anArray at: i + 1 put: ((spec at: 3) ifNil: [i] ifNotNilDo: [:sym| sym])].
- [:i | anArray at: i + 1 put: ((spec at: 3) ifNil: [i] ifNotNil: [:sym| sym])].
  contiguous := contiguous + ((spec at: 2) - (spec at: 1)) + 1]]!

Item was changed:
  ----- Method: StackInterpreterSimulator>>run (in category 'testing') -----
  run
  "Just run"
  quitBlock := [([transcript dependents anyOne outermostMorphThat: [:m| m isSystemWindow]]
  on: Error
  do: [:ex| nil])
+ ifNotNilDo: [:window| (UIManager default confirm: 'close?') ifTrue: [window delete]].
- ifNotNil: [:window| (UIManager default confirm: 'close?') ifTrue: [window delete]].
   ^self].
  self initStackPages.
  self loadInitialContext.
  self internalizeIPandSP.
  self fetchNextBytecode.
  [true] whileTrue:
  [self assertValidExecutionPointers.
  atEachStepBlock value. "N.B. may be nil"
  self dispatchOn: currentBytecode in: BytecodeTable.
  self incrementByteCount].
  localIP := localIP - 1.
  "undo the pre-increment of IP before returning"
  self externalizeIPandSP!

Item was changed:
  ----- Method: StackInterpreterSimulator>>runWithBreakCount: (in category 'testing') -----
  runWithBreakCount: theBreakCount
  "Just run, halting when byteCount is reached"
  quitBlock := [(displayView notNil
    and: [UIManager default confirm: 'close?']) ifTrue:
+ [(displayView outermostMorphThat: [:m| m isSystemWindow]) ifNotNilDo:
- [(displayView outermostMorphThat: [:m| m isSystemWindow]) ifNotNil:
  [:topWindow| topWindow delete]].
   ^self].
  breakCount := theBreakCount.
  self initStackPages.
  self loadInitialContext.
  self internalizeIPandSP.
  self fetchNextBytecode.
  [true] whileTrue:
  [self assertValidExecutionPointers.
  self dispatchOn: currentBytecode in: BytecodeTable.
  self incrementByteCount].
  localIP := localIP - 1.
  "undo the pre-increment of IP before returning"
  self externalizeIPandSP!

Item was changed:
  ----- Method: StackInterpreterSimulator>>utilitiesMenu: (in category 'UI') -----
  utilitiesMenu: aMenuMorph
  aMenuMorph
  add: 'toggle transcript' action: #toggleTranscript;
  addLine;
  add: 'print ext head frame' action: #printExternalHeadFrame;
  add: 'print int head frame' action: #printHeadFrame;
  add: 'short print frame & callers' action: [self shortPrintFrameAndCallers: framePointer];
  add: 'long print frame & callers' action: [self printFrameAndCallers: framePointer SP: stackPointer];
+ add: 'print frame...' target: self action: [(self promptHex: 'print frame') ifNotNilDo: [:fp| self printFrame: fp]];
- add: 'print frame...' target: self action: [(self promptHex: 'print frame') ifNotNil: [:fp| self printFrame: fp]];
  add: 'print call stack' action: #printCallStack;
+ add: 'print oop...' action: [(self promptHex: 'print oop') ifNotNilDo: [:oop| self printOop: oop]];
- add: 'print oop...' action: [(self promptHex: 'print oop') ifNotNil: [:oop| self printOop: oop]];
  addLine;
  add: 'inspect object memory' target: objectMemory action: #inspect;
  add: 'inspect cointerpreter' action: #inspect;
  addLine;
  add: 'set break count...' action: #setBreakCount;
  add: (printSends
  ifTrue: ['no print sends']
  ifFalse: ['print sends'])
  action: [self ensureDebugAtEachStepBlock.
  printSends := printSends not];
  "currently printReturns does nothing"
  "add: (printReturns
  ifTrue: ['no print returns']
  ifFalse: ['print returns'])
  action: [self ensureDebugAtEachStepBlock.
  printReturns := printReturns not];"
  add: (printBytecodeAtEachStep
  ifTrue: ['no print bytecode each bytecode']
  ifFalse: ['print bytecode each bytecode'])
  action: [self ensureDebugAtEachStepBlock.
  printBytecodeAtEachStep := printBytecodeAtEachStep not];
  add: (printFrameAtEachStep
  ifTrue: ['no print frame each bytecode']
  ifFalse: ['print frame each bytecode'])
  action: [self ensureDebugAtEachStepBlock.
  printFrameAtEachStep := printFrameAtEachStep not].
  ^aMenuMorph!

Item was changed:
  ----- Method: TCaseStmtNode>>assumesCurrentBytecodeMatchesCaseValue: (in category 'as yet unclassified') -----
  assumesCurrentBytecodeMatchesCaseValue: statementList
  "Test for the special case of certain methods that rely on the value of
  the currentBytecode variable to be expanded to a constant. This is a
  performance optimization that permits the next bytecode to be fetched
  early while not affecting the prior value of currentBytecode, which
  will have been translated to a constant.
 
  See senders of #'requires currentBytecode to be expanded to a constant'
  for methods that rely on this behavior."
 
  | trickySelectors commentString firstLine |
  trickySelectors := {
  #pushLiteralConstantBytecode .
  #pushLiteralVariableBytecode .
  #pushReceiverVariableBytecode .
  #pushTemporaryVariableBytecode .
  #storeAndPopTemporaryVariableBytecode .
  #storeAndPopReceiverVariableBytecode
  }.
  firstLine := statementList statements first.
  firstLine isComment ifTrue: [
  commentString := firstLine asString.
+ trickySelectors detect: [:e | self string: commentString includesSubstring: e]
- trickySelectors detect: [:e | commentString includesSubString: e]
  ifNone: [^ false].
  ^ true].
  ^ false!

Item was changed:
  ----- Method: TMethod>>addTypeForSelf (in category 'utilities') -----
  addTypeForSelf
  "If self should be typed then add a suitable type declaration.
  Preserve the flagging of an implicit self using the #implicit symbol as the fake type."
+ self typeForSelf ifNotNilDo:
- self typeForSelf ifNotNil:
  [:typeForSelf|
  self declarationAt: 'self'
  put: (typeForSelf == #implicit
  ifTrue: [typeForSelf]
  ifFalse: [typeForSelf, ' self'])]!

Item was changed:
  ----- Method: TMethod>>argConversionExprFor:stackIndex: (in category 'primitive compilation') -----
  argConversionExprFor: varName stackIndex: stackIndex
  "Return the parse tree for an expression that fetches and converts the
  primitive argument at the given stack offset."
  | exprList decl stmtList |
  exprList := OrderedCollection new.
  (declarations includesKey: varName) ifTrue:[
  decl := declarations at: varName.
  (decl includes: $*) ifTrue:["array"
+ (self string: decl includesSubstring: 'char') ifTrue:[ | expr |
- (decl includesSubString: 'char') ifTrue:[ | expr |
  expr := '(interpreterProxy isBytes: (interpreterProxy stackValue: (stackIndex))) ifFalse:[^interpreterProxy primitiveFail].'.
  expr := expr copyReplaceAll: 'interpreterProxy' with: self vmNameString.
  expr := expr copyReplaceAll: 'stackIndex' with: stackIndex printString.
  exprList add: expr.
  ].
  exprList add: varName , ' := ', self vmNameString, ' arrayValueOf: (', self vmNameString, ' stackValue: (' , stackIndex printString , '))'.
  exprList add: varName , ' := ' , varName , ' - 1'.
  ] ifFalse:["must be a double"
  (decl findString: 'double' startingAt: 1) = 0 ifTrue: [
  self error: 'unsupported type declaration in a primitive method'
  ].
  exprList add: varName , ' := ', self vmNameString, ' stackFloatValue: ' , stackIndex printString.
  ]
  ] ifFalse: ["undeclared variables are taken to be integer"
  exprList add: varName , ' := ', self vmNameString, ' stackIntegerValue: ' , stackIndex printString
  ].
  stmtList := OrderedCollection new.
  exprList do: [:e | stmtList addAll: (self statementsFor: e varName: varName)].
  ^ stmtList!

Item was changed:
  ----- Method: TMethod>>emitCFunctionPrototype:generator:newlineBeforeName: (in category 'C code generation') -----
  emitCFunctionPrototype: aStream generator: aCodeGen newlineBeforeName: newlineBeforeName "<Boolean>"
  "Emit a C function header for this method onto the given stream."
 
  export
  ifTrue:[aStream nextPutAll: 'EXPORT('; nextPutAll: returnType; nextPut: $)]
  ifFalse:[(self isStaticIn: aCodeGen) ifTrue:[aStream nextPutAll: 'static '].
  aStream nextPutAll: returnType].
  newlineBeforeName ifTrue: [aStream cr] ifFalse: [aStream space].
  (returnType last = $)
+ and: [self string: returnType includesSubstring: (aCodeGen cFunctionNameFor: self selectorForCodeGeneration)]) ifTrue:
- and: [returnType includesSubString: (aCodeGen cFunctionNameFor: self selectorForCodeGeneration)]) ifTrue:
  ["Hack fix for e.g. <returnTypeC: 'void (*setInterruptCheckChain(void (*aFunction)(void)))()'>"
  ^self].
  aStream
  nextPutAll: (aCodeGen cFunctionNameFor: self selectorForCodeGeneration);
  nextPut: $(.
  args isEmpty
  ifTrue: [aStream nextPutAll: #void]
  ifFalse:
  [args
  do: [:arg| aStream nextPutAll: (self declarationAt: arg)]
  separatedBy: [ aStream nextPutAll: ', ' ]].
  aStream nextPut: $)!

Item was changed:
  ----- Method: TMethod>>extractDirective:valueBlock:default: (in category 'transformations') -----
  extractDirective: theSelector valueBlock: aBlock default: defaultResult
  "Find a pragma of the form:
 
  <theSelector[args]>
 
  Answer the result of evaluating aBock with a TSendNode corresponding
  to the pragma node, or defaultResult if there is no matching pragma."
 
  | result found newStatements |
+ (properties at: theSelector ifAbsent: []) ifNotNilDo:
- (properties at: theSelector ifAbsent: []) ifNotNil:
  [:pragma|
  ^aBlock value: (TSendNode new
  setSelector: pragma keyword
  receiver: (TVariableNode new setName: 'self')
  arguments: (pragma arguments collect: [:const| TConstantNode new setValue: const]))].
  "Pre-pragma backward compatibility:
  Scan the top-level statements for a labelling directive of the form:
 
  self theSelector[args]
 
  and remove the directive from the method body if found.
  Answer the result of evaluating aBock with the send node,
   or defaultResult if there is no labelling directive." result := defaultResult.
  found := false.
  newStatements := OrderedCollection new: parseTree statements size.
  parseTree statements do:
  [ :stmt |
  (stmt isSend
  and: [stmt selector = theSelector])
  ifTrue:
  [found := true.
  result := aBlock value: stmt]
  ifFalse:
  [newStatements add: stmt]].
  ^found
  ifTrue:
  [parseTree setStatements: newStatements asArray.
  result]
  ifFalse: [defaultResult]!

Item was changed:
  ----- Method: TMethod>>maybeBreakFor:in: (in category 'inlining') -----
  maybeBreakFor: aNode in: aCodeGen
  "convenient for debugging..."
  (aNode isSend
  and: [(aCodeGen breakSrcInlineSelector notNil or: [aCodeGen breakDestInlineSelector notNil])
+ and: [(aCodeGen breakSrcInlineSelector ifNil: [true] ifNotNilDo: [:srcSel| srcSel = aNode selector])
+ and: [aCodeGen breakDestInlineSelector ifNil: [true] ifNotNilDo: [:dstSel| dstSel = selector]]]]) ifTrue:
- and: [(aCodeGen breakSrcInlineSelector ifNil: [true] ifNotNil: [:srcSel| srcSel = aNode selector])
- and: [aCodeGen breakDestInlineSelector ifNil: [true] ifNotNil: [:dstSel| dstSel = selector]]]]) ifTrue:
  [self halt: selector]!

Item was changed:
  ----- Method: TMethod>>superExpansionNodeFor:args: (in category 'inlining') -----
  superExpansionNodeFor: aSelector args: argumentNodes
  "Answer the expansion of a super send.  Merge the super expansion's
  locals, properties and comment into this method's properties."
  (definingClass superclass lookupSelector: aSelector)
  ifNil: [self error: 'superclass does not define super method']
+ ifNotNilDo:
- ifNotNil:
  [:superMethod| | superTMethod commonVars varMap |
  superTMethod := superMethod methodNode asTranslationMethodOfClass: self class.
  ((argumentNodes allSatisfy: [:parseNode| parseNode isVariableNode])
  and: [(argumentNodes asOrderedCollection collect: [:parseNode| parseNode key]) = superTMethod args]) ifFalse:
  [self error: definingClass name, '>>',selector, ' args ~= ',
  superTMethod definingClass name, '>>', aSelector,
  (String with: $. with: Character cr),
  'For super expansions to be translated correctly each argument must be a variable with the same name as the corresponding argument in the super method.'].
  self mergePropertiesOfSuperMethod: superTMethod.
  (commonVars := superTMethod locals intersection: self locals) notEmpty ifTrue:
  [varMap := Dictionary new.
  commonVars do:
  [:k| varMap at: k put: (superTMethod unusedNamePrefixedBy: k avoiding: self allLocals)].
  superTMethod renameVariablesUsing: varMap].
  self assert: (superTMethod locals allSatisfy: [:var| (self locals includes: var) not]).
  locals addAll: superTMethod locals.
  superTMethod declarations keysAndValuesDo:
  [:var :decl|
  self declarationAt: var put: decl].
+ superTMethod comment ifNotNilDo:
- superTMethod comment ifNotNil:
  [:superComment|
  comment := comment
  ifNil: [superComment]
+ ifNotNilDo: [superComment, comment]].
+ superTMethod extraVariableNumber ifNotNilDo:
- ifNotNil: [superComment, comment]].
- superTMethod extraVariableNumber ifNotNil:
  [:scvn|
  extraVariableNumber := extraVariableNumber ifNil: [scvn] ifNotNil: [:cvn| cvn + scvn]].
  superTMethod elideAnyFinalReturn.
  ^superTMethod parseTree]!

Item was changed:
  ----- Method: TMethod>>tryToInlineMethodsIn: (in category 'inlining') -----
  tryToInlineMethodsIn: aCodeGen
  "Expand any (complete) inline methods called by this method. Set the complete bit when all inlining has been done. Return true if something was inlined."
 
  | stmtLists didSomething newStatements sendsToInline |
  self definedAsMacro ifTrue:
  [complete := true.
  ^false].
  didSomething := false.
  sendsToInline := Dictionary new: 100.
  parseTree
  nodesDo:
  [:node|
  (self inlineableFunctionCall: node in: aCodeGen) ifTrue:
  [sendsToInline at: node put: (self inlineFunctionCall: node in: aCodeGen)]]
  unless: "Don't inline the arguments to asserts to keep the asserts readable"
  [:node|
  node isSend
  and: [aCodeGen isAssertSelector: node selector]].
 
  sendsToInline isEmpty ifFalse:
  [didSomething := true.
  self removeUnreferencedDeclarations.
  parseTree := parseTree replaceNodesIn: sendsToInline].
 
  didSomething ifTrue:
  [writtenToGlobalVarsCache := nil.
  ^didSomething].
 
  stmtLists := self statementsListsForInliningIn: aCodeGen.
  stmtLists do:
  [:stmtList|
  newStatements := OrderedCollection new: 100.
  stmtList statements do:
  [:stmt|
  (self inlineCodeOrNilForStatement: stmt in: aCodeGen)
  ifNil: [newStatements addLast: stmt]
+ ifNotNilDo: [:inlinedStmts|
- ifNotNil: [:inlinedStmts|
  didSomething := true.
  newStatements addAllLast: inlinedStmts]].
  stmtList setStatements: newStatements asArray].
 
  didSomething ifTrue:
  [writtenToGlobalVarsCache := nil.
  ^didSomething].
 
  complete ifFalse:
  [self checkForCompleteness: stmtLists in: aCodeGen.
  complete ifTrue: [ didSomething := true ]].  "marking a method complete is progress"
  ^didSomething!

Item was changed:
  ----- Method: TSendNode>>isStructSend: (in category 'testing') -----
  isStructSend: aCodeGen
  "Answer if the recever is a send of a structure accessor.
  This is tricky.  We want
  foo bar => foo->bar
  foo bar => foo.bar
  foo bar: expr => foo->bar = expr
  foo bar: expr => foo.bar = expr
  depending on whether foo is a struct or a pointer to a struct,
  but only if both foo is a struct type and bar is a field accessor.
  The tricky cases are self-sends within struct class methods.  Here we need to
  distinguish between self-sends of ordinary methods from self sends of accessors."
  ^arguments size <= 1
    and: [(receiver structTargetKind: aCodeGen) notNil
    and: [(aCodeGen methodNamed: selector)
  ifNil: [false]
+ ifNotNilDo: [:method| method isStructAccessor]]]!
- ifNotNil: [:method| method isStructAccessor]]]!

Item was changed:
  ----- Method: TSendNode>>isStructSendIn: (in category 'testing') -----
  isStructSendIn: aCodeGen
  "Answer if the recever is a send of a structure accessor.
  This is tricky.  We want
  foo bar => foo->bar
  foo bar => foo.bar
  foo bar: expr => foo->bar = expr
  foo bar: expr => foo.bar = expr
  depending on whether foo is a struct or a pointer to a struct,
  but only if both foo is a struct type and bar is a field accessor.
  The tricky cases are self-sends within struct class methods.  Here we need to
  distinguish between self-sends of ordinary methods from self sends of accessors."
  ^arguments size <= 1
    and: [(receiver structTargetKindIn: aCodeGen) notNil
    and: [(aCodeGen methodNamed: selector)
  ifNil: [false]
+ ifNotNilDo: [:method| method isStructAccessor]]]!
- ifNotNil: [:method| method isStructAccessor]]]!

Item was changed:
  ----- Method: TSendNode>>structTargetKindIn: (in category 'testing') -----
  structTargetKindIn: aCodeGen
  "Answer if the recever evaluates to a struct or struct pointer
  and hence can be dereferenced using . or ->.  Answer any of
  #struct #pointer or nil.  Right now we don't need or support
  structure return so this method answers either #pointer or nil."
  selector == #cCoerceSimple:to: ifTrue:
  [^(VMStructType isTypePointerToStruct: arguments last value) ifTrue:
  [#pointer]].
 
  selector == #addressOf: ifTrue:
  [^#pointer].
 
  selector == #at: ifTrue:
  [receiver isVariable ifTrue:
+ [(aCodeGen typeOfVariable: receiver name) ifNotNilDo:
- [(aCodeGen typeOfVariable: receiver name) ifNotNil:
  [:type| | derefType |
  type last = $* ifFalse:
  [^receiver structTargetKindIn: aCodeGen].
  (VMStructType isTypeStruct: (aCodeGen
  extractTypeFor: receiver name
  fromDeclaration: type allButLast)) ifTrue:
  [^#struct]]].
+ (receiver structTargetKindIn: aCodeGen) ifNotNilDo:
- (receiver structTargetKindIn: aCodeGen) ifNotNil:
  [:kind| ^kind]].
 
  (aCodeGen selectorReturnsPointerToStruct: selector) ifTrue:
  [^#pointer].
 
  (aCodeGen selectorReturnsStruct: selector) ifTrue:
  [^#struct].
 
  ^nil!

Item was changed:
  ----- Method: VMMaker class>>forceNewFileNamed: (in category 'utilities') -----
+ forceNewFileNamed: fileName
+ "Use CrLfFileStream for older images such as Squeak 3.6, or MultiByteFileStream
+ if CrLfFileStream is no longer present. LrLfFileStream is first choice because
+ forceNewFileNamed: was a late addition to MultiByteFileStream."
- forceNewFileNamed: aFilename
- "Always output files in unix lf format.
- A single format is friendlier to e.g. external version control systems.
- The Microsoft and old MacOS classic C compilers all accept lf format files."
 
+ (Smalltalk classNamed: 'CrLfFileStream')
+ ifNotNilDo: [ :crlf | ^ crlf forceNewFileNamed: fileName ].
+ (Smalltalk classNamed: 'MultiByteFileStream')
+ ifNotNilDo: [ :cls | ^ ((cls forceNewFileNamed: fileName) lineEndConvention: #lf; yourself) ].
+ !
- ^(MultiByteFileStream forceNewFileNamed: aFilename)
- lineEndConvention: #lf;
- yourself!

Item was changed:
  ----- Method: VMMakerTool>>entryRowWithLabel:labelWidth:balloonText:getFieldText:setFieldText:buttonLabel:buttonAction:buttonBalloonText: (in category 'window construction') -----
  entryRowWithLabel: label labelWidth: lWidth balloonText: balloonText getFieldText: getTextSelector setFieldText: setTextSelector buttonLabel: buttonLabel buttonAction: buttonAction buttonBalloonText: buttonBalloonText
  | row tm |
  row := Morph new color: Color transparent;
  hResizing: #spaceFill;
  vResizing: #spaceFill;
  extent: 550 @ 40;
  layoutPolicy: ProportionalLayout new;
  borderWidth: 2;
  setBalloonText: balloonText translated;
  yourself.
  row
  addMorph: (TextMorph new contents: label translated asText allBold) lock
  fullFrame: (LayoutFrame
  fractions: (0 @ 0 corner: 0 @ 1)
  offsets: (3 @ 3 corner: lWidth @ -3)).
  row
  addMorph: ((tm := PluggableTextMorph
  on: self
  text: getTextSelector
+ accept: setTextSelector) acceptOnCR: true)
- accept: setTextSelector) hideVScrollBarIndefinitely: true;
- acceptOnCR: true)
  fullFrame: (LayoutFrame
  fractions: (0 @ 0 corner: 1 @ 1)
  offsets: (lWidth + 10 @ 0 corner: (lWidth / 1.8 + 10) negated @ 0)).
  "Make the background a solid color so that eventual bleed from the labels doesn't make the entire input field unreadable. Happens when the bold font is significantly wider than the non-bold font or when the spacing of the font doesn't match the guess above"
  tm color: (Color gray: 0.9).
  buttonAction
  ifNotNil: [row
  addMorph: (SimpleButtonMorph new target: self;
  label: buttonLabel translated;
  actionSelector: buttonAction;
  hResizing: #spaceFill;
  setBalloonText: buttonBalloonText translated)
  fullFrame: (LayoutFrame
  fractions: (1 @ 0 corner: 1 @ 1)
  offsets: ((lWidth / 1.8 + 5) negated @ 3 corner: -5 @ -3))].
  ^ row!

Item was changed:
  ----- Method: VMStructType class>>checkGenerateFieldAccessors:bitPosition:in: (in category 'code generation') -----
  checkGenerateFieldAccessors: fieldSpecs bitPosition: firstBitPosition in: surrogateClass
  | bitPosition alignedByteSize |
  bitPosition := firstBitPosition.
  fieldSpecs do:
  [:spec| | code |
  "If the accessor is already defined in a superclass don't redefine it in the subclass.
  We assume it is correctly defined in the superclass."
  (spec first ~= #unused
  and: [(surrogateClass whichClassIncludesSelector: spec first asSymbol)
  ifNil: [true]
+ ifNotNilDo: [:implementingClass|
- ifNotNil: [:implementingClass|
  self assert: (implementingClass inheritsFrom: Object).
  implementingClass == surrogateClass]]) ifTrue:
  [code := self getter: spec first
  bitPosition: bitPosition
  bitWidth: spec second
  bool: (spec at: 3 ifAbsent: []) = #Boolean.
  code ~= (surrogateClass sourceCodeAt: spec first asSymbol ifAbsent: ['']) asString ifTrue:
  [surrogateClass compile: code classified: #accessing].
  code := self setter: spec first
  bitPosition: bitPosition
  bitWidth: spec second
  bool: (spec at: 3 ifAbsent: []) = #Boolean.
  code ~= (surrogateClass sourceCodeAt: (spec first, ':') asSymbol ifAbsent: ['']) asString ifTrue:
  [surrogateClass compile: code classified: #accessing]].
  bitPosition := bitPosition + spec second].
  alignedByteSize := bitPosition / 8.
  self assert: alignedByteSize isInteger.
  alignedByteSize ~= surrogateClass alignedByteSize ifTrue:
  [surrogateClass class
  compile: 'alignedByteSize'
  , (String with: Character cr with: Character tab with: $^)
  , alignedByteSize printString
  classified: #accessing]!

Item was changed:
  ----- Method: VMStructType class>>needsTypeTag (in category 'translation') -----
  needsTypeTag
  self instVarNamesAndTypesForTranslationDo:
  [:ivn :type|
+ (self string: (type isArray ifTrue: [type first] ifFalse: [type]) includesSubstring: self structTagName) ifTrue:
- ((type isArray ifTrue: [type first] ifFalse: [type]) includesSubString: self structTagName) ifTrue:
  [^true]].
  ^false!