VM Maker: VMMaker.oscog-eem.2720.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.oscog-eem.2720.mcz

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

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

Name: VMMaker.oscog-eem.2720
Author: eem
Time: 24 February 2020, 9:57:51.683539 am
UUID: 36860558-04f0-4fda-b52f-062b2386286d
Ancestors: VMMaker.oscog-eem.2719

Cogit:
Change return value for not-found of methodFor: from 0 to nil.

#define codeToDataDelta as 0 for the non DUAL_MAPPED_CODE_ZONE regime.

Fix followForwardedLiteralsIn:, mapObjectReferencesInMachineCodeForXXX, and storeLiteral:atAnnotatedAddress:using: for the DUAL_MAPPED_CODE_ZONE regime.

Inlcude the method in question in armPrintDualZoneAnomalies output.

Fix printMethodFieldForPrintContext: to always print the method oop frst and the cogMethod, if any, afterwards.

Fix asserts in frameCallerContext: and mapStackPages when a frame context may be forwarded as part of scavenging.

Slang: Fix sizeOfIntegralCType: for the more complex defnition of codeToDataDelta.

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

Item was changed:
  ----- Method: CCodeGenerator>>sizeOfIntegralCType: (in category 'inlining') -----
  sizeOfIntegralCType: anIntegralCType "<String>"
  "N.B. Only works for values for which isIntegralCType: answers true."
  | prunedCType index |
- (anIntegralCType beginsWith: 'register ') ifTrue:
- [^self sizeOfIntegralCType: (anIntegralCType allButFirst: 9)].
  prunedCType := (anIntegralCType beginsWith: 'unsigned ')
  ifTrue: [(anIntegralCType allButFirst: 9) withBlanksTrimmed]
  ifFalse: [(anIntegralCType beginsWith: 'signed ')
  ifTrue: [(anIntegralCType allButFirst: 7) withBlanksTrimmed]
  ifFalse: [anIntegralCType]].
 
  ^prunedCType asString caseOf: {
  ['sqLong'] -> [8].
  ['usqLong'] -> [8].
  ['long long'] -> [8].
  ['sqInt'] -> [BytesPerOop].
  ['usqInt'] -> [BytesPerOop].
  ['sqIntptr_t'] -> [BytesPerWord].
  ['usqIntptr_t'] -> [BytesPerWord].
  ['int'] -> [4].
  ['short'] -> [2].
  ['short int'] -> [2].
  ['char'] -> [1].
  ['long'] -> [BytesPerWord]. "It's ambiguous on LLP64 and we'll later remove it"
  ['size_t'] -> [BytesPerWord].
  ['pid_t'] -> [BytesPerWord].
  }
  otherwise:
+ [(anIntegralCType beginsWith: 'register ') ifTrue:
+ [^self sizeOfIntegralCType: (anIntegralCType allButFirst: 9)].
+ (anIntegralCType beginsWith: 'static ') ifTrue:
+ [^self sizeOfIntegralCType: (anIntegralCType allButFirst: 7)].
+ ((anIntegralCType beginsWith: 'unsigned') "e.g. 'unsigned  : 8'"
- [((anIntegralCType beginsWith: 'unsigned') "e.g. 'unsigned  : 8'"
   and: [(anIntegralCType includesAnyOf: '[*]') not
+  and: [(index := anIntegralCType indexOf: $:) > 0]]) ifTrue:
+ [^(Integer readFrom: (anIntegralCType copyFrom: index + 1 to: anIntegralCType size) withBlanksTrimmed readStream) + 7 // 8].
+ anIntegralCType first = $# ifTrue:
+ [(anIntegralCType subStrings: '\') do:
+ [:substring|
+ substring first ~~ $# ifTrue:
+ [([self sizeOfIntegralCType: substring withBlanksTrimmed]
+ on: Error
+ do: [:ex| nil]) ifNotNil: [:size| ^size]]]].
+ self error: 'unrecognized integral type']!
-  and: [(index := anIntegralCType indexOf: $:) > 0]])
- ifTrue: [(Integer readFrom: (anIntegralCType copyFrom: index + 1 to: anIntegralCType size) withBlanksTrimmed readStream) + 7 // 8]
- ifFalse: [self error: 'unrecognized integral type']]!

Item was changed:
  ----- Method: CoInterpreter>>checkOkayFields: (in category 'debug support') -----
  checkOkayFields: oop
  "Check if the argument is an ok object.
  If this is a pointers object, check that its fields are all okay oops."
 
  | hasYoung i fieldOop |
  (oop = nil or: [oop = 0]) ifTrue: [ ^true ]. "?? eem 1/16/2013"
  (objectMemory isIntegerObject: oop) ifTrue: [ ^true ].
  (objectMemory checkOkayOop: oop) ifFalse: [ ^false ].
  (objectMemory checkOopHasOkayClass: oop) ifFalse: [ ^false ].
  ((objectMemory isPointersNonImm: oop) or: [objectMemory isCompiledMethod: oop]) ifFalse: [ ^true ].
  hasYoung := objectMemory hasSpurMemoryManagerAPI not
   and: [objectMemory isYoungObject: (objectMemory fetchClassOfNonImm: oop)].
  (objectMemory isCompiledMethod: oop)
  ifTrue:
  [i := (objectMemory literalCountOf: oop) + LiteralStart - 1]
  ifFalse:
  [(objectMemory isContext: oop)
  ifTrue: [i := CtxtTempFrameStart + (self fetchStackPointerOf: oop) - 1]
  ifFalse: [i := (objectMemory lengthOf: oop) - 1]].
  [i >= 0] whileTrue:
  [fieldOop := objectMemory fetchPointer: i ofObject: oop.
  (objectMemory isNonIntegerObject: fieldOop) ifTrue:
  [(i = 0 and: [objectMemory isCompiledMethod: oop])
  ifTrue:
+ [(cogMethodZone methodFor: (self pointerForOop: fieldOop)) ifNil:
- [(cogMethodZone methodFor: (self pointerForOop: fieldOop)) = 0 ifTrue:
  [self print: 'method '; printHex: oop; print: ' has an invalid cog method reference'.
  ^false]]
  ifFalse:
  [hasYoung := hasYoung or: [objectMemory isYoung: fieldOop].
  (objectMemory checkOkayOop: fieldOop) ifFalse: [ ^false ].
  (self checkOopHasOkayClass: fieldOop) ifFalse: [ ^false ]]].
  i := i - 1].
  hasYoung ifTrue:
  [^objectMemory checkOkayYoungReferrer: oop].
  ^true!

Item was changed:
  ----- Method: CoInterpreter>>frameCallerContext: (in category 'frame access') -----
  frameCallerContext: theFP
  "In the StackInterpreter the saved ip field of a base frame holds the
  base frame's caller context. But in the Cog VM the first word on the
  stack holds the base frame's caller context, which is immediately
  above the stacked receiver."
  <var: #theFP type: #'char *'>
  | thePage callerContextOrNil |
  <var: #thePage type: #'StackPage *'>
  self assert: (self isBaseFrame: theFP).
  thePage := stackPages stackPageFor: theFP.
  callerContextOrNil := stackPages longAt: thePage baseAddress.
  self assert: (objectMemory addressCouldBeObj: callerContextOrNil).
+ self assert: (callerContextOrNil = objectMemory nilObject or: [objectMemory isContext: (objectMemory followMaybeForwarded: callerContextOrNil)]).
- self assert: (callerContextOrNil = objectMemory nilObject or: [objectMemory isContext: callerContextOrNil]).
  ^callerContextOrNil!

Item was changed:
  ----- Method: CoInterpreter>>mapStackPages (in category 'object memory support') -----
  mapStackPages
  <inline: #never>
  <var: #thePage type: #'StackPage *'>
  <var: #theSP type: #'char *'>
  <var: #theFP type: #'char *'>
  <var: #frameRcvrOffset type: #'char *'>
  <var: #callerFP type: #'char *'>
  <var: #theIPPtr type: #'char *'>
  | numLivePages |
  numLivePages := 0.
  0 to: numStackPages - 1 do:
  [:i| | thePage theSP theFP frameRcvrOffset callerFP theIPPtr theIP oop |
  thePage := stackPages stackPageAt: i.
  thePage isFree ifFalse:
  [self assert: (self ifCurrentStackPageHasValidHeadPointers: thePage).
  numLivePages := numLivePages + 1.
  theSP := thePage headSP.
  theFP := thePage  headFP.
  "Skip the instruction pointer on top of stack of inactive pages."
  thePage = stackPage
  ifTrue: [theIPPtr := ((self isMachineCodeFrame: theFP)
  or: [(self iframeSavedIP: theFP) = 0])
  ifTrue: [0]
  ifFalse: [theFP + FoxIFSavedIP]]
  ifFalse:
  [theIPPtr := theSP.
  theSP := theSP + objectMemory wordSize].
  [self assert: (thePage addressIsInPage: theFP).
  self assert: (thePage addressIsInPage: theSP).
  self assert: (theIPPtr = 0 or: [thePage addressIsInPage: theIPPtr]).
  frameRcvrOffset := self frameReceiverLocation: theFP.
   [theSP <= frameRcvrOffset] whileTrue:
  [oop := stackPages longAt: theSP.
  (objectMemory shouldRemapOop: oop) ifTrue:
  [stackPages longAt: theSP put: (objectMemory remapObj: oop)].
  theSP := theSP + objectMemory wordSize].
  (self frameHasContext: theFP) ifTrue:
  [(objectMemory shouldRemapObj: (self frameContext: theFP)) ifTrue:
  [stackPages
  longAt: theFP + FoxThisContext
  put: (objectMemory remapObj: (self frameContext: theFP))].
  "With SqueakV3 objectMemory or SpurPlanningCompactor can't assert since object body is yet to move."
  (objectMemory hasSpurMemoryManagerAPI
+  and: [(objectMemory slidingCompactionInProgress or: [objectMemory scavengeInProgress]) not]) ifTrue:
-  and: [objectMemory slidingCompactionInProgress not]) ifTrue:
  [self assert: ((self isMarriedOrWidowedContext: (self frameContext: theFP))
  and: [(self frameOfMarriedContext: (self frameContext: theFP)) = theFP])]].
  (self isMachineCodeFrame: theFP) ifFalse:
  [(objectMemory shouldRemapObj: (self iframeMethod: theFP)) ifTrue:
  [theIPPtr ~= 0 ifTrue:
  [theIP := stackPages longAt: theIPPtr.
  theIP = cogit ceReturnToInterpreterPC
  ifTrue:
  [self assert: (self iframeSavedIP: theFP) > (self iframeMethod: theFP).
  theIPPtr := theFP + FoxIFSavedIP.
  theIP := stackPages longAt: theIPPtr]
  ifFalse:
  [self assert: theIP > (self iframeMethod: theFP)].
  theIP := theIP - (self iframeMethod: theFP)].
  stackPages
  longAt: theFP + FoxMethod
  put: (objectMemory remapObj: (self iframeMethod: theFP)).
  theIPPtr ~= 0 ifTrue:
  [stackPages longAt: theIPPtr put: theIP + (self iframeMethod: theFP)]]].
  (callerFP := self frameCallerFP: theFP) ~= 0] whileTrue:
  [theSP := (theIPPtr := theFP + FoxCallerSavedIP) + objectMemory wordSize.
  theFP := callerFP].
  theSP := theFP + FoxCallerSavedIP + objectMemory wordSize.
  [theSP <= thePage baseAddress] whileTrue:
  [oop := stackPages longAt: theSP.
  (objectMemory shouldRemapOop: oop) ifTrue:
  [stackPages longAt: theSP put: (objectMemory remapObj: oop)].
  theSP := theSP + objectMemory wordSize]]].
  stackPages recordLivePagesOnMapping: numLivePages!

Item was changed:
  ----- Method: CoInterpreter>>printMethodFieldForPrintContext: (in category 'debug printing') -----
  printMethodFieldForPrintContext: aContext
  <inline: true>
  | meth |
  meth := objectMemory fetchPointer: MethodIndex ofObject: aContext.
+ self printOopShortInner: meth.
+ (self methodHasCogMethod: meth) ifTrue:
+ [self space; print: '('; printHexnp: (self cogMethodOf: meth); print: ')'].
+ self cr!
- (self isMarriedOrWidowedContext: aContext)
- ifFalse:
- [self printOopShortInner: meth.
- (self methodHasCogMethod: meth) ifTrue:
- [self space; print: '('; printHexnp: (self cogMethodOf: meth); print: ')'].
- self cr]
- ifTrue:
- [(self methodHasCogMethod: meth) ifTrue:
- [self printHexnp: (self cogMethodOf: meth); space].
- self shortPrintOop: meth]!

Item was changed:
  ----- Method: CoInterpreter>>printMethodHeaderOop: (in category 'debug printing') -----
  printMethodHeaderOop: anOop
  "Print the CogMethod and its header if this is a CogMethod reference."
- | cogMethod |
  <var: #cogMethod type: #'CogMethod *'>
  (self isCogMethodReference: anOop) ifTrue:
+ [(cogMethodZone methodFor: (self pointerForOop: anOop)) ifNotNil:
+ [:cogMethod| ^self printHex: anOop; space; printDecodeMethodHeaderOop: cogMethod methodHeader]].
- [cogMethod := cogMethodZone methodFor: (self pointerForOop: anOop).
- cogMethod ~= 0 ifTrue:
- [^self printHex: anOop; space; printDecodeMethodHeaderOop: cogMethod methodHeader]].
  ^self printDecodeMethodHeaderOop: anOop!

Item was changed:
  ----- Method: CogMethodZone>>methodFor: (in category 'jit - api') -----
  methodFor: address
  <api>
  <returnTypeC: #'CogMethod *'>
  <var: #address type: #'void *'>
  | cogMethod nextMethod |
- <var: #cogMethod type: #'CogMethod *'>
- <var: #nextMethod type: #'CogMethod *'>
  cogMethod := coInterpreter cCoerceSimple: baseAddress to: #'CogMethod *'.
  [cogMethod < self limitZony
  and: [cogMethod asUnsignedInteger <= address asUnsignedInteger]] whileTrue:
  [nextMethod := self methodAfter: cogMethod.
  nextMethod = cogMethod ifTrue:
+ [^nil].
- [^0].
  (address asUnsignedInteger >= cogMethod asUnsignedInteger
   and: [address asUnsignedInteger < nextMethod asUnsignedInteger]) ifTrue:
  [^cogMethod].
  cogMethod := nextMethod].
+ ^nil!
- ^0!

Item was changed:
  ----- Method: Cogit class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: aCCodeGenerator
  | backEnd |
  backEnd := CogCompilerClass basicNew.
  #( 'coInterpreter' 'objectMemory' 'methodZone' 'objectRepresentation'
  'cogBlockMethodSurrogateClass' 'cogMethodSurrogateClass' 'nsSendCacheSurrogateClass'
  'threadManager' 'processor' 'lastNInstructions' 'simulatedAddresses'
  'simulatedTrampolines' 'simulatedVariableGetters' 'simulatedVariableSetters'
  'processorFrameValid' 'printRegisters' 'printInstructions' 'clickConfirm' 'singleStep') do:
  [:simulationVariableNotNeededForRealVM|
  aCCodeGenerator removeVariable: simulationVariableNotNeededForRealVM].
  NewspeakVM ifFalse:
  [#( 'selfSendTrampolines' 'dynamicSuperSendTrampolines'
  'implicitReceiverSendTrampolines' 'outerSendTrampolines'
  'ceEnclosingObjectTrampoline' 'numIRCs' 'indexOfIRC' 'theIRCs') do:
  [:variableNotNeededInNormalVM|
  aCCodeGenerator removeVariable: variableNotNeededInNormalVM]].
  aCCodeGenerator removeConstant: #COGMTVM. "this should be defined at compile time"
  aCCodeGenerator
  addHeaderFile:'<stddef.h>'; "for e.g. offsetof"
  addHeaderFile:'"sqCogStackAlignment.h"';
  addHeaderFile:'"dispdbg.h"'; "must precede cointerp.h & cogit.h otherwise NoDbgRegParms gets screwed up"
  addHeaderFile:'"cogmethod.h"'.
  NewspeakVM ifTrue:
  [aCCodeGenerator addHeaderFile:'"nssendcache.h"'].
  aCCodeGenerator
  addHeaderFile:'#if COGMTVM';
  addHeaderFile:'"cointerpmt.h"';
  addHeaderFile:'#else';
  addHeaderFile:'"cointerp.h"';
  addHeaderFile:'#endif';
  addHeaderFile:'"cogit.h"'.
  aCCodeGenerator
  var: #ceGetFP
  declareC: 'usqIntptr_t (*ceGetFP)(void)';
  var: #ceGetSP
  declareC: 'usqIntptr_t (*ceGetSP)(void)';
  var: #ceCaptureCStackPointers
  declareC: 'void (*ceCaptureCStackPointers)(void)';
  var: #ceEnterCogCodePopReceiverReg
  declareC: 'void (*ceEnterCogCodePopReceiverReg)(void)';
  var: #realCEEnterCogCodePopReceiverReg
  declareC: 'void (*realCEEnterCogCodePopReceiverReg)(void)';
  var: #ceCallCogCodePopReceiverReg
  declareC: 'void (*ceCallCogCodePopReceiverReg)(void)';
  var: #realCECallCogCodePopReceiverReg
  declareC: 'void (*realCECallCogCodePopReceiverReg)(void)';
  var: #ceCallCogCodePopReceiverAndClassRegs
  declareC: 'void (*ceCallCogCodePopReceiverAndClassRegs)(void)';
  var: #realCECallCogCodePopReceiverAndClassRegs
  declareC: 'void (*realCECallCogCodePopReceiverAndClassRegs)(void)';
  var: #postCompileHook
  declareC: 'void (*postCompileHook)(CogMethod *)';
  var: #openPICList declareC: 'CogMethod *openPICList = 0';
  var: #maxMethodBefore type: #'CogBlockMethod *';
  var: 'enumeratingCogMethod' type: #'CogMethod *'.
 
  aCCodeGenerator
  var: #ceTryLockVMOwner
  declareC: '#if COGMTVM\usqIntptr_t (*ceTryLockVMOwner)(void)';
  var: #ceUnlockVMOwner
  declareC: 'void (*ceUnlockVMOwner)(void)\#endif /* COGMTVM */'.
 
  backEnd numCheckLZCNTOpcodes > 0 ifTrue:
  [aCCodeGenerator
  var: #ceCheckLZCNTFunction
  declareC: 'static usqIntptr_t (*ceCheckLZCNTFunction)(void)'].
  backEnd numCheckFeaturesOpcodes > 0 ifTrue:
  [aCCodeGenerator
  var: #ceCheckFeaturesFunction
  declareC: 'static usqIntptr_t (*ceCheckFeaturesFunction)(void)'].
  backEnd numICacheFlushOpcodes > 0 ifTrue:
  [aCCodeGenerator
  var: #ceFlushICache
  declareC: 'static void (*ceFlushICache)(usqIntptr_t from, usqIntptr_t to)'].
  aCCodeGenerator
  var: #ceFlushDCache
+ declareC: '#if DUAL_MAPPED_CODE_ZONE\static void (*ceFlushDCache)(usqIntptr_t from, usqIntptr_t to)\#endif';
+ var: #codeToDataDelta
+ declareC: '#if DUAL_MAPPED_CODE_ZONE\static sqInt codeToDataDelta\#else\# define codeToDataDelta 0\#endif'.
- declareC: '#if DUAL_MAPPED_CODE_ZONE\static void (*ceFlushDCache)(usqIntptr_t from, usqIntptr_t to)\#endif'.
 
  aCCodeGenerator
  declareVar: 'aMethodLabel' type: #'AbstractInstruction'; "Has to come lexicographically before backEnd & methodLabel"
  var: #backEnd declareC: 'AbstractInstruction * const backEnd = &aMethodLabel';
  var: #methodLabel declareC: 'AbstractInstruction * const methodLabel = &aMethodLabel'.
  self declareC: #(abstractOpcodes stackCheckLabel
  blockEntryLabel blockEntryNoContextSwitch
  stackOverflowCall sendMiss
  entry noCheckEntry selfSendEntry dynSuperEntry
  fullBlockNoContextSwitchEntry fullBlockEntry
  picMNUAbort picInterpretAbort  endCPICCase0 endCPICCase1 cPICEndOfCodeLabel)
  as: #'AbstractInstruction *'
  in: aCCodeGenerator.
  aCCodeGenerator
  declareVar: #cPICPrototype type: #'CogMethod *';
  declareVar: #blockStarts type: #'BlockStart *';
  declareVar: #fixups type: #'BytecodeFixup *';
  declareVar: #methodZoneBase type: #usqInt.
  aCCodeGenerator
  var: #ordinarySendTrampolines
  declareC: 'sqInt ordinarySendTrampolines[NumSendTrampolines]';
  var: #superSendTrampolines
  declareC: 'sqInt superSendTrampolines[NumSendTrampolines]'.
  BytecodeSetHasDirectedSuperSend ifTrue:
  [aCCodeGenerator
  var: #directedSuperSendTrampolines
  declareC: 'sqInt directedSuperSendTrampolines[NumSendTrampolines]';
  var: #directedSuperBindingSendTrampolines
  declareC: 'sqInt directedSuperBindingSendTrampolines[NumSendTrampolines]'].
  NewspeakVM ifTrue:
  [aCCodeGenerator
  var: #selfSendTrampolines
  declareC: 'sqInt selfSendTrampolines[NumSendTrampolines]';
  var: #dynamicSuperSendTrampolines
  declareC: 'sqInt dynamicSuperSendTrampolines[NumSendTrampolines]';
  var: #implicitReceiverSendTrampolines
  declareC: 'sqInt implicitReceiverSendTrampolines[NumSendTrampolines]';
  var: #outerSendTrampolines
  declareC: 'sqInt outerSendTrampolines[NumSendTrampolines]'].
  aCCodeGenerator
  var: #trampolineAddresses
  declareC: 'static char *trampolineAddresses[NumTrampolines*2]';
  var: #objectReferencesInRuntime
  declareC: 'static usqInt objectReferencesInRuntime[NumObjRefsInRuntime+1]';
  var: #labelCounter
  type: #int;
  var: #traceFlags
  declareC: 'int traceFlags = 8 /* prim trace log on by default */';
  var: #cStackAlignment
  declareC: 'const int cStackAlignment = STACK_ALIGN_BYTES'.
  aCCodeGenerator
  declareVar: #minValidCallAddress type: #'usqIntptr_t';
  declareVar: #debugPrimCallStackOffset type: #'usqIntptr_t'.
  aCCodeGenerator vmClass generatorTable ifNotNil:
  [:bytecodeGenTable|
  aCCodeGenerator
  var: #generatorTable
  declareC: 'static BytecodeDescriptor generatorTable[', bytecodeGenTable size printString, ']',
  (self tableInitializerFor: bytecodeGenTable
  in: aCCodeGenerator)].
  "In C the abstract opcode names clash with the Smalltalk generator syntactic sugar.
  Most of the syntactic sugar is inlined, but alas some remains.  Rename the syntactic
  sugar to avoid the clash."
  (self organization listAtCategoryNamed: #'abstract instructions') do:
  [:s|
  aCCodeGenerator addSelectorTranslation: s to: 'g', (aCCodeGenerator cFunctionNameFor: s)].
  aCCodeGenerator addSelectorTranslation: #halt: to: 'haltmsg'.
  self declareFlagVarsAsByteIn: aCCodeGenerator!

Item was changed:
  ----- Method: Cogit>>armPrintDualZoneAnomalies (in category 'debugging') -----
  armPrintDualZoneAnomalies
  <doNotGenerate>
+ | badRangeStart out |
- | badRangeStart |
  codeToDataDelta > 0 ifTrue:
+ [out := coInterpreter transcript.
+ codeBase to: methodZone zoneEnd - 4 by: 4 do:
- [codeBase to: methodZone zoneEnd - 4 by: 4 do:
  [:address|
+ (objectMemory long32At: address) = (objectMemory long32At: address + codeToDataDelta)
- (objectMemory long32At: address) = (objectMemory long32At: address + codeToDataDelta)
  ifTrue:
  [badRangeStart ifNotNil:
+ [out
- [coInterpreter transcript
  ensureCr;
  nextPutAll: 'anomaly '; nextPutAll: badRangeStart hex; nextPutAll: ' to: '; nextPutAll: (address - 4) hex;
  nextPutAll: ' vs ';
+ nextPutAll: (badRangeStart + codeToDataDelta) hex; nextPutAll: ' to: '; nextPutAll: (address + codeToDataDelta - 4) hex.
+ (methodZone methodFor: badRangeStart) ifNotNil:
+ [:cogMethod| out nextPutAll: ' (method '; nextPutAll: cogMethod address hex; nextPut: $)].
+ out cr; flush].
- nextPutAll: (badRangeStart + codeToDataDelta) hex; nextPutAll: ' to: '; nextPutAll: (address + codeToDataDelta - 4) hex;
- cr; flush].
  badRangeStart := nil]
  ifFalse:
  [badRangeStart ifNil: [badRangeStart := address]]].
  badRangeStart ifNotNil:
+ [out
- [coInterpreter transcript
  ensureCr;
  nextPutAll: 'anomaly '; nextPutAll: badRangeStart hex; nextPutAll: ' to: '; nextPutAll: (methodZone zoneEnd - 4) hex;
  nextPutAll: ' vs ';
+ nextPutAll: (badRangeStart + codeToDataDelta) hex; nextPutAll: ' to: '; nextPutAll: (methodZone zoneEnd + codeToDataDelta - 4) hex.
+ (methodZone methodFor: badRangeStart) ifNotNil:
+ [:cogMethod| out nextPutAll: ' (method '; nextPutAll: cogMethod address hex; nextPut: $)].
+ out cr; flush]].
- nextPutAll: (badRangeStart + codeToDataDelta) hex; nextPutAll: ' to: '; nextPutAll: (methodZone zoneEnd + codeToDataDelta - 4) hex;
- cr; flush]].
  ^nil!

Item was changed:
  ----- Method: Cogit>>followForwardedLiteralsIn: (in category 'garbage collection') -----
  followForwardedLiteralsIn: cogMethod
  <api>
  <option: #SpurObjectMemory>
  <var: #cogMethod type: #'CogMethod *'>
+ | writableCogMethod hasYoungObj hasYoungObjPtr |
- | hasYoungObj hasYoungObjPtr |
  self assert: (cogMethod cmType ~= CMMethod or: [(objectMemory isForwarded: cogMethod methodObject) not]).
+ writableCogMethod := self writableMethodFor: cogMethod.
  hasYoungObj := objectMemory isYoung: cogMethod methodObject.
  (objectMemory shouldRemapOop: cogMethod selector) ifTrue:
+ [writableCogMethod selector: (objectMemory remapObj: cogMethod selector).
- [cogMethod selector: (objectMemory remapObj: cogMethod selector).
  (objectMemory isYoung: cogMethod selector) ifTrue:
  [hasYoungObj := true]].
  hasYoungObjPtr := (self addressOf: hasYoungObj put: [:val| hasYoungObj := val]) asInteger.
  self mapFor: cogMethod
  performUntil: #remapIfObjectRef:pc:hasYoung:
  arg: hasYoungObjPtr.
  hasYoungObj
  ifTrue: [methodZone ensureInYoungReferrers: cogMethod]
+ ifFalse: [writableCogMethod cmRefersToYoung: false]!
- ifFalse: [cogMethod cmRefersToYoung: false]!

Item was changed:
  ----- Method: Cogit>>lookupAddress: (in category 'disassembly') -----
  lookupAddress: address
  <doNotGenerate>
- | cogMethod |
  address < methodZone freeStart ifTrue:
  [address >= methodZoneBase
  ifTrue:
+ [(methodZone methodFor: address) ifNotNil:
+ [:cogMethod|
- [(cogMethod := methodZone methodFor: address) ~= 0 ifTrue:
- [cogMethod := self cCoerceSimple: cogMethod to: #'CogMethod *'.
  ^((cogMethod selector ~= objectMemory nilObject
     and: [objectRepresentation couldBeObject: cogMethod selector])
  ifTrue: [coInterpreter stringOf: cogMethod selector]
  ifFalse: [cogMethod asInteger hex]),
    '@', ((address - cogMethod asInteger) hex allButFirst: 3)]]
  ifFalse:
  [^address = (self codeEntryFor: address) ifTrue:
  [self codeEntryNameFor: address]].
  ^nil].
  (simulatedTrampolines includesKey: address) ifTrue:
  [^self labelForSimulationAccessor: (simulatedTrampolines at: address)].
  (simulatedVariableGetters includesKey: address) ifTrue:
  [^self labelForSimulationAccessor: (simulatedVariableGetters at: address)].
  ^(coInterpreter lookupAddress: address) ifNil:
  [address = self cStackPointerAddress
  ifTrue: [#CStackPointer]
  ifFalse:
  [address = self cFramePointerAddress ifTrue:
  [#CFramePointer]]]!

Item was changed:
  ----- Method: Cogit>>mapObjectReferencesInMachineCodeForBecome (in category 'garbage collection') -----
  mapObjectReferencesInMachineCodeForBecome
  "Update all references to objects in machine code for a become.
  Unlike incrementalGC or fullGC a method that does not refer to young may
  refer to young as a result of the become operation.  Unlike incrementalGC
  or fullGC the reference from a Cog method to its methodObject *must not*
  change since the two are two halves of the same object."
+ | cogMethod writableCogMethod hasYoungObj hasYoungObjPtr freedPIC |
- | cogMethod hasYoungObj hasYoungObjPtr freedPIC |
- <var: #cogMethod type: #'CogMethod *'>
  hasYoungObj := false.
  hasYoungObjPtr := (self addressOf: hasYoungObj put: [:val| hasYoungObj := val]) asInteger.
  codeModified := freedPIC := false.
  self mapObjectReferencesInGeneratedRuntime.
  cogMethod := self cCoerceSimple: methodZoneBase to: #'CogMethod *'.
  [cogMethod < methodZone limitZony] whileTrue:
  [self assert: hasYoungObj not.
  cogMethod cmType ~= CMFree ifTrue:
  [self assert: (self cogMethodDoesntLookKosher: cogMethod) = 0.
+ writableCogMethod := self writableMethodFor: cogMethod.
+ writableCogMethod selector: (objectRepresentation remapOop: cogMethod selector).
- cogMethod selector: (objectRepresentation remapOop: cogMethod selector).
  cogMethod cmType = CMClosedPIC
  ifTrue:
  [((objectMemory isYoung: cogMethod selector)
    or: [self mapObjectReferencesInClosedPIC: cogMethod]) ifTrue:
  [freedPIC := true.
  methodZone freeMethod: cogMethod]]
  ifFalse:
  [(objectMemory isYoung: cogMethod selector) ifTrue:
  [hasYoungObj := true].
  cogMethod cmType = CMMethod ifTrue:
  [| remappedMethod |
  self assert: cogMethod objectHeader = objectMemory nullHeaderForMachineCodeMethod.
  remappedMethod := objectRepresentation remapOop: cogMethod methodObject.
  remappedMethod ~= cogMethod methodObject ifTrue:
  [(coInterpreter methodHasCogMethod: remappedMethod) ifTrue:
  [self error: 'attempt to become two cogged methods'].
  (objectMemory
  withoutForwardingOn: cogMethod methodObject
  and: remappedMethod
  with: cogMethod cmUsesPenultimateLit
  sendToCogit: #method:hasSameCodeAs:checkPenultimate:) ifFalse:
  [self error: 'attempt to become cogged method into different method'].
  "For non-Newspeak there should ne a one-to-one mapping between bytecoded and
   cog methods.  For Newspeak not necessarily, but only for anonymous accessors."
  "Only reset the method object's header if it is referring to this CogMethod."
  (coInterpreter rawHeaderOf: cogMethod methodObject) = cogMethod asInteger
  ifTrue:
  [coInterpreter
  rawHeaderOf: cogMethod methodObject
  put: cogMethod methodHeader.
+ writableCogMethod
- cogMethod
  methodHeader: (coInterpreter rawHeaderOf: remappedMethod);
  methodObject: remappedMethod.
  coInterpreter
  rawHeaderOf: remappedMethod
  put: cogMethod asInteger]
  ifFalse:
  [self assert: (self noAssertMethodClassAssociationOf: cogMethod methodObject)
  = objectMemory nilObject.
+ writableCogMethod
- cogMethod
  methodHeader: (coInterpreter rawHeaderOf: remappedMethod);
  methodObject: remappedMethod]].
  (objectMemory isYoung: cogMethod methodObject) ifTrue:
  [hasYoungObj := true]].
  self mapFor: cogMethod
  performUntil: #remapIfObjectRef:pc:hasYoung:
  arg: hasYoungObjPtr.
  hasYoungObj
  ifTrue:
  [methodZone ensureInYoungReferrers: cogMethod.
  hasYoungObj := false]
  ifFalse:
  [cogMethod cmRefersToYoung: false]]].
  cogMethod := methodZone methodAfter: cogMethod].
  "we /must/ prune youngReferrers here because a) the [cogMethod cmRefersToYoung: false]
  block could have removed a method and subsequently it could be added back, and b) we
  can not tolerate duplicates in the youngReferrers list."  
  methodZone pruneYoungReferrers.
  freedPIC ifTrue:
  [self unlinkSendsToFree].
  codeModified ifTrue: "After updating oops in inline caches we need to flush the icache."
  [backEnd flushICacheFrom: codeBase asUnsignedInteger to: methodZone limitZony asUnsignedInteger]!

Item was changed:
  ----- Method: Cogit>>mapObjectReferencesInMachineCodeForFullGC (in category 'garbage collection') -----
  mapObjectReferencesInMachineCodeForFullGC
  "Update all references to objects in machine code for a full gc.  Since
  the current (New)ObjectMemory GC makes everything old in a full GC
  a method not referring to young will not refer to young afterwards"
+ | cogMethod writableCogMethod |
- | cogMethod |
- <var: #cogMethod type: #'CogMethod *'>
  codeModified := false.
  self mapObjectReferencesInGeneratedRuntime.
  cogMethod := self cCoerceSimple: methodZoneBase to: #'CogMethod *'.
  [cogMethod < methodZone limitZony] whileTrue:
  [cogMethod cmType ~= CMFree ifTrue:
  [self assert: (self cogMethodDoesntLookKosher: cogMethod) = 0.
+ writableCogMethod := self writableMethodFor: cogMethod.
+ writableCogMethod selector: (objectRepresentation remapOop: cogMethod selector).
- cogMethod selector: (objectRepresentation remapOop: cogMethod selector).
  cogMethod cmType = CMClosedPIC
  ifTrue:
  [self assert: cogMethod cmRefersToYoung not.
  self mapObjectReferencesInClosedPIC: cogMethod]
  ifFalse:
  [cogMethod cmType = CMMethod ifTrue:
  [self assert: cogMethod objectHeader = objectMemory nullHeaderForMachineCodeMethod.
+ writableCogMethod methodObject: (objectRepresentation remapOop: cogMethod methodObject)].
- cogMethod methodObject: (objectRepresentation remapOop: cogMethod methodObject)].
  self mapFor: cogMethod
  performUntil: #remapIfObjectRef:pc:hasYoung:
  arg: 0.
  (cogMethod cmRefersToYoung
   and: [objectRepresentation allYoungObjectsAgeInFullGC]) ifTrue:
+ [writableCogMethod cmRefersToYoung: false]]].
- [cogMethod cmRefersToYoung: false]]].
  cogMethod := methodZone methodAfter: cogMethod].
  methodZone pruneYoungReferrers.
  codeModified ifTrue: "After updating oops in inline caches we need to flush the icache."
  [backEnd flushICacheFrom: codeBase asUnsignedInteger to: methodZone limitZony asUnsignedInteger]!

Item was changed:
  ----- Method: Cogit>>mapObjectReferencesInMachineCodeForYoungGC (in category 'garbage collection') -----
  mapObjectReferencesInMachineCodeForYoungGC
  "Update all references to objects in machine code for either a Spur scavenging gc
  or a Squeak V3 incremental GC.  Avoid scanning all code by using the youngReferrers
  list.  In a young gc a method referring to young may no longer refer to young, but a
  method not referring to young cannot and will not refer to young afterwards."
  | pointer cogMethod hasYoungObj hasYoungObjPtr |
- <var: #cogMethod type: #'CogMethod *'>
  hasYoungObj := false.
  hasYoungObjPtr := (self addressOf: hasYoungObj put: [:val| hasYoungObj := val]) asInteger.
  codeModified := false.
  pointer := methodZone youngReferrers.
  [pointer < methodZone zoneEnd] whileTrue:
  [self assert: hasYoungObj not.
  cogMethod := coInterpreter cCoerceSimple: (objectMemory longAt: pointer) to: #'CogMethod *'.
  cogMethod cmType = CMFree
  ifTrue: [self assert: cogMethod cmRefersToYoung not]
  ifFalse:
  [self assert: (self cogMethodDoesntLookKosher: cogMethod) = 0.
  cogMethod cmRefersToYoung ifTrue:
+ [| writableCogMethod |
- [| writableVersion |
  self assert: (cogMethod cmType = CMMethod
  or: [cogMethod cmType = CMOpenPIC]).
+ writableCogMethod := self writableMethodFor: cogMethod.
+ writableCogMethod selector: (objectRepresentation remapOop: cogMethod selector).
- writableVersion := self writableMethodFor: cogMethod.
- writableVersion selector: (objectRepresentation remapOop: cogMethod selector).
  (objectMemory isYoung: cogMethod selector) ifTrue:
  [hasYoungObj := true].
  cogMethod cmType = CMMethod ifTrue:
  [self assert: cogMethod objectHeader = objectMemory nullHeaderForMachineCodeMethod.
+ writableCogMethod methodObject: (objectRepresentation remapOop: cogMethod methodObject).
- writableVersion methodObject: (objectRepresentation remapOop: cogMethod methodObject).
  (objectMemory isYoung: cogMethod methodObject) ifTrue:
  [hasYoungObj := true]].
  self mapFor: cogMethod
  performUntil: #remapIfObjectRef:pc:hasYoung:
  arg: hasYoungObjPtr.
  hasYoungObj
  ifTrue: [hasYoungObj := false]
+ ifFalse: [writableCogMethod cmRefersToYoung: false]]].
- ifFalse: [writableVersion cmRefersToYoung: false]]].
  pointer := pointer + objectMemory wordSize].
  methodZone pruneYoungReferrers.
  codeModified ifTrue: "After updating oops in inline caches we need to flush the icache."
  [backEnd flushICacheFrom: methodZoneBase asUnsignedInteger to: methodZone limitZony asUnsignedInteger]!

Item was changed:
  ----- Method: Cogit>>printCogMethodFor: (in category 'printing') -----
  printCogMethodFor: address
  <api>
  <var: #address type: #'void *'>
+ (methodZone methodFor: address)
+ ifNil: [(self codeEntryFor: address)
- | cogMethod |
- <var: #cogMethod type: #'CogMethod *'>
- cogMethod := methodZone methodFor: address.
- cogMethod = 0
- ifTrue: [(self codeEntryFor: address)
  ifNil: [coInterpreter print: 'not a method'; cr]
  ifNotNil: [coInterpreter print: 'trampoline '; print: (self codeEntryNameFor: address); cr]]
+ ifNotNil: [:cogMethod| coInterpreter printCogMethod: cogMethod]!
- ifFalse: [coInterpreter printCogMethod: cogMethod]!

Item was changed:
  ----- Method: Cogit>>printCogMethodHeaderFor: (in category 'printing') -----
  printCogMethodHeaderFor: address
  <doNotGenerate>
+ (methodZone methodFor: address)
+ ifNil: [coInterpreter print: 'not a method'; cr]
+ ifNotNil: [:cogMethod| self printMethodHeader: cogMethod on: coInterpreter transcript]!
- | cogMethod |
- <var: #cogMethod type: #'CogMethod *'>
- cogMethod := methodZone methodFor: address.
- cogMethod = 0
- ifTrue: [coInterpreter print: 'not a method'; cr]
- ifFalse: [self printMethodHeader: cogMethod on: coInterpreter transcript]!

Item was changed:
  ----- Method: InLineLiteralsManager>>storeLiteral:atAnnotatedAddress:using: (in category 'garbage collection') -----
  storeLiteral: literal atAnnotatedAddress: address using: instruction
  "Normally literals are embedded in instructions and the annotation is at the start of
  the following instruction, to cope with literals embedded in variable-length instructions,
  since, e.g. on x86, the literal typically comes at the end of the instruction."
  <var: 'address' type: #usqInt>
  <var: 'instruction' type: #'AbstractInstruction *'>
+ <inline: #always>
- <inline: true>
  ^instruction storeLiteral: literal beforeFollowingAddress: address!

Item was changed:
  ----- Method: OutOfLineLiteralsManager>>storeLiteral:atAnnotatedAddress:using: (in category 'garbage collection') -----
  storeLiteral: literal atAnnotatedAddress: address using: instruction
  "With out-of-line literals, the IsObjectReference annotation refers to
  the start of the literal and hence access the memory directly."
  <var: 'address' type: #usqInt>
  <var: 'instruction' type: #'AbstractInstruction *'>
+ <inline: #always>
+ cogit codeLongAt: address put: literal!
- <inline: true>
- objectMemory longAt: address put: literal!