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

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

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

Name: VMMaker.oscog-eem.530
Author: eem
Time: 4 December 2013, 3:07:26.276 pm
UUID: cb1992ae-2118-40a3-9cee-8c9c89fcc30a
Ancestors: VMMaker.oscog-eem.529

Fix bad bugs in Spur machine-code instantiation prims and access
scavengeThreshold as a constant.  Rename the accessor to
getScavengeThreshold for slang.

Indicate ceReturnToInterpreterPC in CoInterpreter frame printing.

Make CogMethodZone>>freeStart a macro to give unfettered
access to the memory manager's freeStart in gdb.

Add printInstancesOf: to SpurMemMgr.

Make printMethodCache translate so as to include it in the real VM.

Simulation:
Provide a simulation-only register map print for making sense of
machine code.

Fix printing of characters, avoiding printing wide characters to avoid
filling the transcript with ?'s.

Fix instruction printing regression.

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

Item was changed:
  ----- Method: CoInterpreter>>printFrame:WithSP: (in category 'debug printing') -----
  printFrame: theFP WithSP: theSP
  <api>
  | theMethod theMethodEnd numArgs numTemps rcvrAddress topThing |
  <inline: false>
  <var: #theFP type: #'char *'>
  <var: #theSP type: #'char *'>
  <var: #addr type: #'char *'>
  <var: #rcvrAddress type: #'char *'>
  <var: #cogMethod type: #'CogBlockMethod *'>
  <var: #homeMethod type: #'CogMethod *'>
  self cCode: '' inSmalltalk: [self transcript ensureCr].
  (self isMachineCodeFrame: theFP)
  ifTrue:
  [| cogMethod homeMethod |
  cogMethod := self mframeCogMethod: theFP.
  homeMethod := self mframeHomeMethod: theFP.
  theMethod := homeMethod asInteger.
  theMethodEnd := homeMethod asInteger + homeMethod blockSize.
  numArgs := cogMethod cmNumArgs.
  numTemps := self temporaryCountOfMethodHeader: homeMethod methodHeader]
  ifFalse:
  [theMethod := self frameMethodObject: theFP.
  theMethodEnd := theMethod + (objectMemory sizeBitsOfSafe: theMethod).
  numArgs := self iframeNumArgs: theFP.
  numTemps := self tempCountOf: theMethod].
  (self frameIsBlockActivation: theFP) ifTrue:
  [| rcvrOrClosure |
  rcvrOrClosure := self pushedReceiverOrClosureOfFrame: theFP.
  ((objectMemory isNonImmediate: rcvrOrClosure)
  and: [(objectMemory addressCouldBeObj: rcvrOrClosure)
  and: [(objectMemory fetchClassOfNonImm: rcvrOrClosure) = (objectMemory splObj: ClassBlockClosure)]])
  ifTrue: [numTemps := numArgs + (self stSizeOf: rcvrOrClosure)]
  ifFalse: [numTemps := 0]].
  self shortPrintFrame: theFP.
  (self isBaseFrame: theFP) ifTrue:
  [self printFrameOop: '(caller ctxt'
  at: theFP + (self frameStackedReceiverOffset: theFP) + (2 * BytesPerWord).
  self printFrameOop: '(saved ctxt'
  at: theFP + (self frameStackedReceiverOffset: theFP) + (1 * BytesPerWord)].
  self printFrameOop: 'rcvr/clsr'
  at: theFP + FoxCallerSavedIP + ((numArgs + 1) * BytesPerWord).
  numArgs to: 1 by: -1 do:
  [:i|
  self printFrameOop: 'arg' index: numArgs - i at: theFP + FoxCallerSavedIP + (i * BytesPerWord)].
+ self printFrameThing: 'caller ip'
+ at: theFP + FoxCallerSavedIP
+ extraString: ((stackPages longAt: theFP + FoxCallerSavedIP) = cogit ceReturnToInterpreterPC ifTrue:
+ ['ceReturnToInterptreter']).
- self printFrameThing: 'caller ip' at: theFP + FoxCallerSavedIP.
  self printFrameThing: 'saved fp' at: theFP + FoxSavedFP.
  self printFrameMethodFor: theFP.
  (self isMachineCodeFrame: theFP) ifFalse:
  [self printFrameFlagsForFP: theFP].
  self printFrameOop: 'context' at: theFP + FoxThisContext.
  (self isMachineCodeFrame: theFP) ifTrue:
  [self printFrameFlagsForFP: theFP].
  (self isMachineCodeFrame: theFP)
  ifTrue: [rcvrAddress := theFP + FoxMFReceiver]
  ifFalse:
  [self printFrameThing: 'saved ip'
  at: theFP + FoxIFSavedIP
  extra: ((self iframeSavedIP: theFP) = 0
  ifTrue: [0]
  ifFalse: [(self iframeSavedIP: theFP) - theMethod + 2 - BaseHeaderSize]).
  rcvrAddress := theFP + FoxIFReceiver].
  self printFrameOop: 'receiver' at: rcvrAddress.
  topThing := stackPages longAt: theSP.
  (topThing between: theMethod and: theMethodEnd)
  ifTrue:
  [rcvrAddress - BytesPerWord to: theSP + BytesPerWord by: BytesPerWord negated do:
  [:addr| | index |
  index := rcvrAddress - addr / BytesPerWord + numArgs.
  index <= numTemps
  ifTrue: [self printFrameOop: 'temp' index: index - 1 at: addr]
  ifFalse: [self printFrameOop: 'stck' at: addr]].
  self printFrameThing: 'frame ip'
  at: theSP
  extra: ((self isMachineCodeFrame: theFP)
  ifTrue: [topThing - theMethod]
  ifFalse: [topThing - theMethod + 2 - BaseHeaderSize])]
  ifFalse:
  [rcvrAddress - BytesPerWord to: theSP by: BytesPerWord negated do:
  [:addr| | index |
  index := rcvrAddress - addr / BytesPerWord + numArgs.
  index <= numTemps
  ifTrue: [self printFrameOop: 'temp' index: index - 1 at: addr]
  ifFalse: [self printFrameOop: 'stck' at: addr]]]!

Item was added:
+ ----- Method: CoInterpreter>>printFrameThing:at:extraString: (in category 'debug printing') -----
+ printFrameThing: name at: address extraString: extraStringOrNil
+ | it len |
+ <inline: false>
+ <var: #name type: #'char *'>
+ <var: #address type: #'char *'>
+ <var: #extraStringOrNil type: #'char *'>
+ it := stackPages longAt: address.
+ self printHexPtr: address;
+ printChar: $:.
+ len := self strlen: name.
+ 1 to: 12 - len do: [:i| self space].
+ self print: name;
+ print: ': ';
+ printHex: it.
+ it ~= 0 ifTrue:
+ [self printChar: $=.
+ it = objectMemory nilObject
+ ifTrue: [self print: 'nil']
+ ifFalse:
+ [self printNum: it]].
+ extraStringOrNil ifNotNil: [self space; print: extraStringOrNil].
+ self cr!

Item was added:
+ ----- Method: CogARMCompiler>>generalPurposeRegisterMap (in category 'disassembly') -----
+ generalPurposeRegisterMap
+ <doNotGenerate>
+ "Answer a Dictionary from register getter to register index."
+ ^Dictionary newFromPairs:
+ { #r4. R4.
+ #r5. R5.
+ #r6. R6.
+ #r7. R7.
+ #r8. R8.
+ #r9. R9 }!

Item was added:
+ ----- Method: CogIA32Compiler>>generalPurposeRegisterMap (in category 'disassembly') -----
+ generalPurposeRegisterMap
+ <doNotGenerate>
+ "Answer a Dictionary from register getter to register index."
+ ^Dictionary newFromPairs:
+ { #eax. EAX.
+ #ecx. ECX.
+ #edx. EDX.
+ #ebx. EBX.
+ #esi.  ESI.
+ #edi.  EDI }!

Item was changed:
  ----- Method: CogMethodZone>>freeStart (in category 'accessing') -----
  freeStart
+ "declared as a macro so as not to conflict with the memory manager's freeStart."
+ <cmacro: '() mzFreeStart'>
- <inline: true>
- <returnTypeC: #usqInt>
  ^mzFreeStart!

Item was changed:
  ----- Method: CogObjectRepresentationFor32BitSpur>>genInnerPrimitiveNew: (in category 'primitive generators') -----
  genInnerPrimitiveNew: retNoffset
  "Implement primitiveNew for convenient cases:
  - the receiver has a hash
  - the receiver is fixed size (excluding ephemerons to save instructions & miniscule time)
  - single word header/num slots < numSlotsMask
+ - the result fits in eden (actually below scavengeThreshold)"
- - the result fits in eden"
 
+ | halfHeaderReg fillReg instSpecReg byteSizeReg
+  jumpUnhashed jumpVariableOrEphemeron jumpNoSpace jumpTooBig jumpHasSlots
+  fillLoop skip |
- | halfHeaderReg instSpecReg
-  jumpUnhashed jumpVariableOrEphemeron jumpNoSpace jumpTooBig jumpHasSlots fillLoop skip |
  <var: 'skip' type: #'AbstractInstruction *'>
  <var: 'fillLoop' type: #'AbstractInstruction *'>
  <var: 'jumpTooBig' type: #'AbstractInstruction *'>
  <var: 'jumpHasSlots' type: #'AbstractInstruction *'>
  <var: 'jumpNoSpace' type: #'AbstractInstruction *'>
  <var: 'jumpUnhashed' type: #'AbstractInstruction *'>
  <var: 'jumpVariableOrEphemeron' type: #'AbstractInstruction *'>
 
+ "half header will contain 1st half of header (classIndex/class's hash & format),
+ then 2nd half of header (numSlots/fixed size) and finally fill value (nilObject)."
+ halfHeaderReg := fillReg := SendNumArgsReg.
+ "inst spec will hold class's instance specification, then byte size and finally end of new object."
+ instSpecReg := byteSizeReg := ClassReg.
- "half header will contain classIndex (class's hash) and format, then fixed size and eventually nilObject"
- halfHeaderReg := SendNumArgsReg.
- "inst spec will hold class's instance specification and then byte size and finally numSlots half of header"
- instSpecReg := ClassReg.
 
  "get freeStart as early as possible so as not to wait later..."
  cogit MoveAw: objectMemory freeStartAddress R: Arg1Reg.
  "get class's hash & fail if 0"
  self genGetHashFieldNonImmOf: ReceiverResultReg into: halfHeaderReg.
  jumpUnhashed := cogit JumpZero: 0.
  "get class's format inst var for both inst spec (format field) and num fixed fields"
  self genLoadSlot: InstanceSpecificationIndex sourceReg: ReceiverResultReg destReg: TempReg.
  self genConvertSmallIntegerToIntegerInScratchReg: TempReg.
  cogit MoveR: TempReg R: instSpecReg.
  cogit LogicalShiftRightCq: objectMemory fixedFieldsFieldWidth R: TempReg.
  cogit AndCq: objectMemory formatMask R: TempReg.
  cogit AndCq: objectMemory fixedFieldsOfClassFormatMask R: instSpecReg.
  "fail if not fixed or if ephemeron (rare beasts so save the cycles)"
  cogit CmpCq: objectMemory nonIndexablePointerFormat R: TempReg.
  jumpVariableOrEphemeron := cogit JumpAbove: 0.
  cogit CmpCq: objectMemory numSlotsMask R: instSpecReg.
  jumpTooBig := cogit JumpAboveOrEqual: 0.
  "Add format to classIndex/format half header; other word contains numSlots"
  cogit LogicalShiftLeftCq: objectMemory formatShift R: TempReg.
  cogit AddR: TempReg R: halfHeaderReg.
  "write half header now; it frees halfHeaderReg"
  cogit MoveR: halfHeaderReg Mw: 0 r: Arg1Reg.
  "save unrounded numSlots for header"
  cogit MoveR: instSpecReg R: halfHeaderReg.
  "compute byte size; remember 0-sized objects still need 1 slot & allocation is
  rounded up to 8 bytes."
+ cogit CmpCq: 0 R: byteSizeReg. "a.k.a. instSpecReg"
- cogit CmpCq: 0 R: instSpecReg.
  jumpHasSlots := cogit JumpNonZero: 0.
+ cogit MoveCq: objectMemory baseHeaderSize * 2 R: byteSizeReg.
- cogit MoveCq: objectMemory baseHeaderSize * 2 R: instSpecReg.
  skip := cogit Jump: 0.
  "round up to allocationUnit"
  jumpHasSlots jmpTarget:
+ (cogit MoveR: byteSizeReg R: TempReg).
- (cogit MoveR: instSpecReg R: TempReg).
  cogit AndCq: 1 R: TempReg.
+ cogit AddR: TempReg R: byteSizeReg.
+ cogit AddCq: objectMemory baseHeaderSize / objectMemory wordSize R: byteSizeReg.
+ cogit LogicalShiftLeftCq: objectMemory shiftForWord R: byteSizeReg.
+ skip jmpTarget:
- cogit AddR: TempReg R: instSpecReg.
- cogit AddCq: objectMemory baseHeaderSize / objectMemory wordSize R: instSpecReg.
- cogit LogicalShiftLeftCq: objectMemory shiftForWord R: instSpecReg.
- skip jmpTarget: "get scavengeThreshold (have freeStart already)"
- (cogit MoveAw: objectMemory scavengeThresholdAddress R: TempReg).
  "shift halfHeaderReg to put numSlots in correct place"
+ (cogit LogicalShiftLeftCq: objectMemory numSlotsHalfShift R: halfHeaderReg).
+ "check if allocation fits (freeSize + byteSize < scavengeThreshold); scavengeThreshold is constant."
+ cogit AddR: Arg1Reg R: byteSizeReg.
+ cogit CmpCq: objectMemory getScavengeThreshold R: byteSizeReg.
+ jumpNoSpace := cogit JumpAboveOrEqual: 0.
+ "write back new freeStart; get result. byteSizeReg holds new freeStart, the limit of the object"
+ cogit MoveR: byteSizeReg Aw: objectMemory freeStartAddress.
- cogit LogicalShiftLeftCq: objectMemory numSlotsHalfShift R: halfHeaderReg.
- "check if allocation fits"
- cogit SubR: Arg1Reg R: TempReg.
- cogit CmpR: TempReg R: instSpecReg.
- jumpNoSpace := cogit JumpAbove: 0.
- "get result, increment freeStart and write it back. Arg1Reg holds new freeStart, the limit of the object"
  cogit MoveR: Arg1Reg R: ReceiverResultReg.
- cogit AddR: instSpecReg R: Arg1Reg.
- cogit MoveR: Arg1Reg Aw: objectMemory freeStartAddress.
  "write other half of header (numSlots/identityHash)"
+ cogit MoveR: halfHeaderReg Mw: 4 r: Arg1Reg.
- cogit MoveR: halfHeaderReg Mw: 4 r: ReceiverResultReg.
  "now fill"
+ cogit LoadEffectiveAddressMw: objectMemory baseHeaderSize r: ReceiverResultReg R: Arg1Reg.
+ cogit MoveCq: objectMemory nilObject R: fillReg.
- cogit LoadEffectiveAddressMw: objectMemory baseHeaderSize r: ReceiverResultReg R: instSpecReg.
- cogit MoveCq: objectMemory nilObject R: halfHeaderReg.
  "at least two words; so can make this a [fill 2 words. reached limit?] whileFalse"
  fillLoop :=
+ cogit MoveR: fillReg Mw: 0 r: Arg1Reg.
+ cogit MoveR: fillReg Mw: 4 r: Arg1Reg.
+ cogit AddCq: 8 R: Arg1Reg.
+ cogit CmpR: Arg1Reg R: byteSizeReg.
+ cogit JumpAbove: fillLoop.
- cogit MoveR: halfHeaderReg Mw: 0 r: instSpecReg.
- cogit MoveR: halfHeaderReg Mw: 4 r: instSpecReg.
- cogit AddCq: 8 R: instSpecReg.
- cogit CmpR: Arg1Reg R: instSpecReg.
- cogit JumpBelow: fillLoop.
  cogit RetN: retNoffset.
 
  jumpUnhashed jmpTarget:
  (jumpVariableOrEphemeron jmpTarget:
  (jumpTooBig jmpTarget:
  (jumpNoSpace jmpTarget: cogit Label))).
 
  ^0!

Item was changed:
  ----- Method: CogObjectRepresentationFor32BitSpur>>genInnerPrimitiveNewWithArg: (in category 'primitive generators') -----
  genInnerPrimitiveNewWithArg: retNoffset
  "Implement primitiveNewWithArg for convenient cases:
  - the receiver has a hash
  - the receiver is variable and not compiled method
  - single word header/num slots < numSlotsMask
  - the result fits in eden
  See superclass method for dynamic frequencies of formats.
  For the moment we implement only arrayFormat, firstByteFormat & firstLongFormat"
 
+ | halfHeaderReg fillReg instSpecReg byteSizeReg maxSlots
- | halfHeaderReg instSpecReg maxSlots
   jumpArrayTooBig jumpByteTooBig jumpLongTooBig
   jumpArrayFormat jumpByteFormat jumpBytePrepDone jumpLongPrepDone
   jumpUnhashed jumpNElementsNonInt jumpFailCuzFixed jumpNoSpace jumpHasSlots fillLoop skip |
  <var: 'skip' type: #'AbstractInstruction *'>
  <var: 'fillLoop' type: #'AbstractInstruction *'>
  <var: 'jumpHasSlots' type: #'AbstractInstruction *'>
  <var: 'jumpNoSpace' type: #'AbstractInstruction *'>
  <var: 'jumpUnhashed' type: #'AbstractInstruction *'>
  <var: 'jumpByteFormat' type: #'AbstractInstruction *'>
  <var: 'jumpByteTooBig' type: #'AbstractInstruction *'>
  <var: 'jumpLongTooBig' type: #'AbstractInstruction *'>
  <var: 'jumpArrayFormat' type: #'AbstractInstruction *'>
  <var: 'jumpArrayTooBig' type: #'AbstractInstruction *'>
  <var: 'jumpFailCuzFixed' type: #'AbstractInstruction *'>
  <var: 'jumpBytePrepDone' type: #'AbstractInstruction *'>
  <var: 'jumpLongPrepDone' type: #'AbstractInstruction *'>
  <var: 'jumpNElementsNonInt' type: #'AbstractInstruction *'>
 
+ "half header will contain 1st half of header (classIndex/class's hash & format),
+ then 2nd half of header (numSlots) and finally fill value (nilObject)."
+ halfHeaderReg := fillReg := SendNumArgsReg.
- "half header will contain classIndex (class's hash) and format, and eventually fill value"
- halfHeaderReg := SendNumArgsReg.
  "inst spec will hold class's instance specification and then byte size and finally numSlots half of header"
+ instSpecReg := byteSizeReg := ClassReg.
- instSpecReg := ClassReg.
  "The max slots we'll allocate here are those for a single header"
  maxSlots := objectMemory numSlotsMask - 1.
 
  "get freeStart as early as possible so as not to wait later..."
  cogit MoveAw: objectMemory freeStartAddress R: Arg1Reg.
  "get class's hash & fail if 0"
  self genGetHashFieldNonImmOf: ReceiverResultReg into: halfHeaderReg.
  jumpUnhashed := cogit JumpZero: 0.
  "get index and fail if not a +ve integer"
  cogit MoveR: Arg0Reg R: TempReg.
  jumpNElementsNonInt := self genJumpNotSmallIntegerInScratchReg: TempReg.
  "get class's format inst var for inst spec (format field)"
  self genLoadSlot: InstanceSpecificationIndex sourceReg: ReceiverResultReg destReg: instSpecReg.
  cogit LogicalShiftRightCq: objectMemory fixedFieldsFieldWidth + self numSmallIntegerTagBits R: instSpecReg.
  cogit AndCq: objectMemory formatMask R: instSpecReg.
  "Add format to classIndex/format half header now"
  cogit MoveR: instSpecReg R: TempReg.
  cogit LogicalShiftLeftCq: objectMemory formatShift R: TempReg.
  cogit AddR: TempReg R: halfHeaderReg.
  "get integer value of num fields in TempReg now"
  cogit MoveR: Arg0Reg R: TempReg.
  self genConvertSmallIntegerToIntegerInScratchReg: TempReg.
  "dispatch on format, failing if not variable or if compiled method"
  cogit CmpCq: objectMemory arrayFormat R: instSpecReg.
  jumpArrayFormat := cogit JumpZero: 0.
  cogit CmpCq: objectMemory firstByteFormat R: instSpecReg.
  jumpByteFormat := cogit JumpZero: 0.
  cogit CmpCq: objectMemory firstLongFormat R: instSpecReg.
  jumpFailCuzFixed := cogit JumpNonZero: 0.
 
  cogit CmpCq: (objectMemory integerObjectOf: maxSlots) R: Arg0Reg.
  jumpLongTooBig := cogit JumpAbove: 0.
  "save num elements/slot size to instSpecReg"
  cogit MoveR: TempReg R: instSpecReg.
  "push fill value"
  cogit MoveCq: 0 R: TempReg.
  cogit PushR: TempReg.
  jumpLongPrepDone := cogit Jump: 0. "go allocate"
 
  jumpByteFormat jmpTarget:
  (cogit CmpCq: (objectMemory integerObjectOf: maxSlots * objectMemory wordSize) R: Arg0Reg).
  jumpByteTooBig := cogit JumpAbove: 0.
  "save num elements to instSpecReg"
  cogit MoveR: TempReg R: instSpecReg.
  "compute odd bits and add into halfHeaderReg; oddBits := 4 - nElements bitAnd: 3"
  cogit MoveCq: objectMemory wordSize R: TempReg.
  cogit SubR: instSpecReg R: TempReg.
  cogit AndCq: objectMemory wordSize - 1 R: TempReg.
  cogit LogicalShiftLeftCq: objectMemory formatShift R: TempReg.
  cogit AddR: TempReg R: halfHeaderReg.
  "round up num elements to numSlots in instSpecReg"
  cogit AddCq: objectMemory wordSize - 1 R: instSpecReg.
  cogit LogicalShiftRightCq: objectMemory shiftForWord R: instSpecReg.
  "push fill value"
  cogit MoveCq: 0 R: TempReg.
  cogit PushR: TempReg.
  jumpBytePrepDone := cogit Jump: 0. "go allocate"
 
  jumpArrayFormat jmpTarget:
  (cogit CmpCq: (objectMemory integerObjectOf: maxSlots) R: Arg0Reg).
  jumpArrayTooBig := cogit JumpAbove: 0.
  "save num elements/slot size to instSpecReg"
  cogit MoveR: TempReg R: instSpecReg.
  "push fill value"
  cogit MoveCw: objectMemory nilObject R: TempReg.
  cogit PushR: TempReg.
  "fall through to allocate"
 
  jumpBytePrepDone jmpTarget:
  (jumpLongPrepDone jmpTarget: cogit Label).
 
  "write half header now; it frees halfHeaderReg"
  cogit MoveR: halfHeaderReg Mw: 0 r: Arg1Reg.
  "save numSlots to halfHeaderReg"
  cogit MoveR: instSpecReg R: halfHeaderReg.
  "compute byte size; remember 0-sized objects still need 1 slot & allocation is
  rounded up to 8 bytes."
+ cogit CmpCq: 0 R: byteSizeReg. "a.k.a. instSpecReg"
- cogit CmpCq: 0 R: instSpecReg.
  jumpHasSlots := cogit JumpNonZero: 0.
+ cogit MoveCq: objectMemory baseHeaderSize * 2 R: byteSizeReg.
- cogit MoveCq: objectMemory baseHeaderSize * 2 R: instSpecReg.
  skip := cogit Jump: 0.
  "round up to allocationUnit"
  jumpHasSlots jmpTarget:
+ (cogit MoveR: byteSizeReg R: TempReg).
- (cogit MoveR: instSpecReg R: TempReg).
  cogit AndCq: 1 R: TempReg.
+ cogit AddR: TempReg R: byteSizeReg.
+ cogit AddCq: objectMemory baseHeaderSize / objectMemory wordSize R: byteSizeReg.
+ cogit LogicalShiftLeftCq: objectMemory shiftForWord R: byteSizeReg.
+ skip jmpTarget:
- cogit AddR: TempReg R: instSpecReg.
- cogit AddCq: objectMemory baseHeaderSize / objectMemory wordSize R: instSpecReg.
- cogit LogicalShiftLeftCq: objectMemory shiftForWord R: instSpecReg.
- skip jmpTarget: "get scavengeThreshold (have freeStart already)"
- (cogit MoveAw: objectMemory scavengeThresholdAddress R: TempReg).
  "shift halfHeaderReg to put numSlots in correct place"
+ (cogit LogicalShiftLeftCq: objectMemory numSlotsHalfShift R: halfHeaderReg).
- cogit LogicalShiftLeftCq: objectMemory numSlotsHalfShift R: halfHeaderReg.
  "check if allocation fits"
+ cogit AddR: Arg1Reg R: byteSizeReg.
+ cogit CmpCq: objectMemory getScavengeThreshold R: byteSizeReg.
+ jumpNoSpace := cogit JumpAboveOrEqual: 0.
- cogit SubR: Arg1Reg R: TempReg.
- cogit CmpR: TempReg R: instSpecReg.
- jumpNoSpace := cogit JumpAbove: 0.
  "get result, increment freeStart and write it back. Arg1Reg holds new freeStart, the limit of the object"
  cogit MoveR: Arg1Reg R: ReceiverResultReg.
+ cogit MoveR: byteSizeReg Aw: objectMemory freeStartAddress.
- cogit AddR: instSpecReg R: Arg1Reg.
- cogit MoveR: Arg1Reg Aw: objectMemory freeStartAddress.
  "write other half of header (numSlots/0 identityHash)"
  cogit MoveR: halfHeaderReg Mw: 4 r: ReceiverResultReg.
  "now fill"
+ cogit PopR: fillReg.
+ cogit LoadEffectiveAddressMw: objectMemory baseHeaderSize r: ReceiverResultReg R: Arg1Reg.
- cogit PopR: halfHeaderReg.
- cogit LoadEffectiveAddressMw: objectMemory baseHeaderSize r: ReceiverResultReg R: instSpecReg.
  "at least two words; so can make this a [fill 2 words. reached limit?] whileFalse"
  fillLoop :=
+ cogit MoveR: fillReg Mw: 0 r: Arg1Reg.
+ cogit MoveR: fillReg Mw: 4 r: Arg1Reg.
+ cogit AddCq: 8 R: Arg1Reg.
+ cogit CmpR: Arg1Reg R: byteSizeReg.
+ cogit JumpAbove: fillLoop.
- cogit MoveR: halfHeaderReg Mw: 0 r: instSpecReg.
- cogit MoveR: halfHeaderReg Mw: 4 r: instSpecReg.
- cogit AddCq: 8 R: instSpecReg.
- cogit CmpR: Arg1Reg R: instSpecReg.
- cogit JumpBelow: fillLoop.
  cogit RetN: retNoffset.
 
  "pop discarded fill value & fall through to failure"
  jumpNoSpace jmpTarget: (cogit PopR: TempReg).
 
  jumpUnhashed jmpTarget:
  (jumpFailCuzFixed jmpTarget:
  (jumpArrayTooBig jmpTarget:
  (jumpByteTooBig jmpTarget:
  (jumpLongTooBig jmpTarget:
+ (jumpNElementsNonInt jmpTarget: cogit Label))))).
- (jumpNoSpace jmpTarget:
- (jumpNElementsNonInt jmpTarget: cogit Label)))))).
 
  ^0!

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>genAllocFloatValue:into:scratchReg:scratchReg: (in category 'primitive generators') -----
  genAllocFloatValue: dpreg into: resultReg scratchReg: scratch1 scratchReg: scratch2
  <returnTypeC: #'AbstractInstruction *'>
  | allocSize newFloatHeader jumpFail |
  <var: #jumpFail type: #'AbstractInstruction *'>
  allocSize := objectMemory baseHeaderSize + (objectMemory sizeof: #double).
  newFloatHeader := objectMemory
  headerForSlots: (self sizeof: #double) / objectMemory wordSize
  format: objectMemory firstLongFormat
  classIndex: objectMemory classFloatCompactIndex.
  cogit MoveAw: objectMemory freeStartAddress R: resultReg.
- cogit MoveAw: objectMemory scavengeThresholdAddress R: scratch2.
  cogit LoadEffectiveAddressMw: allocSize r: resultReg R: scratch1.
+ cogit CmpCq: objectMemory getScavengeThreshold R: scratch1.
- cogit CmpR: scratch2 R: scratch1.
  jumpFail := cogit JumpAboveOrEqual: 0.
  cogit MoveR: scratch1 Aw: objectMemory freeStartAddress.
  cogit MoveCq: newFloatHeader R: scratch2.
  objectMemory wordSize = objectMemory baseHeaderSize
  ifTrue: [cogit MoveR: scratch2 Mw: 0 r: resultReg]
  ifFalse:
  [self flag: #endianness.
+ cogit MoveCq: newFloatHeader >> 32 R: scratch1.
- cogit MoveCq: 0 R: scratch1.
  cogit MoveR: scratch2 Mw: 0 r: resultReg.
+ cogit MoveR: scratch1 Mw: objectMemory wordSize r: resultReg].
- cogit MoveR: scratch1 Mw: objectMemory wordSize r: resultReg.].
  cogit MoveRd: dpreg M64: objectMemory baseHeaderSize r: resultReg.
  ^jumpFail!

Item was removed:
- ----- Method: CogRTLOpcodes class>>nameForAbstractRegister: (in category 'debug printing') -----
- nameForAbstractRegister: reg "<Integer>"
- ^#(Arg0Reg Arg1Reg ClassReg FPReg ReceiverResultReg SPReg SendNumArgsReg TempReg
- DPFPReg0 DPFPReg1 DPFPReg2 DPFPReg3 DPFPReg4 DPFPReg5 DPFPReg6 DPFPReg7 LinkReg)
- detect: [:sym| (classPool at: sym) = reg]!

Item was changed:
  ----- Method: CogVMSimulator>>printFrameThing:andFrame:at: (in category 'debug printing') -----
  printFrameThing: name andFrame: theFP at: address
  <var: #theFP type: #'char *'>
  | it |
  <inline: false>
  <var: #name type: #'char *'>
  <var: #address type: #'char *'>
  it := stackPages longAt: address.
  self printHex: address;
  printChar: $:.
  1 to: 12 - (self strlen: name) do: [:i| self printChar: $ ].
  self print: name;
  print: ': ';
  printHex: it.
  it ~= 0 ifTrue:
  [self printChar: $=; printNum: it.
+ (objectMemory isInMemory: it) ifFalse:
- (it between: objectMemory startOfMemory and: objectMemory endOfMemory) ifFalse:
  [(cogit lookupAddress: it) ifNotNil:
  [:label| self space; printChar: $(; print: label; printChar: $)]]].
  self print: ' frame: '; printHex: theFP; cr!

Item was changed:
  ----- Method: CogVMSimulator>>printFrameThing:at: (in category 'debug printing') -----
  printFrameThing: name at: address
  | it |
  <inline: false>
  <var: #name type: #'char *'>
  <var: #address type: #'char *'>
  it := stackPages longAt: address.
  self printHex: address;
  printChar: $:.
  1 to: 12 - (self strlen: name) do: [:i| self printChar: $ ].
  self print: name;
  print: ': ';
  printHex: it.
  it ~= 0 ifTrue:
  [self printChar: $=; printNum: it.
+ (objectMemory isInMemory: it) ifFalse:
- (it between: objectMemory startOfMemory and: objectMemory endOfMemory) ifFalse:
  [(cogit lookupAddress: it) ifNotNil:
  [:label| self space; printChar: $(; print: label; printChar: $)]]].
  self cr!

Item was changed:
  ----- Method: CogVMSimulator>>shortPrint: (in category 'debug support') -----
  shortPrint: oop
  | name classOop |
  (objectMemory isImmediate: oop) ifTrue:
  [(objectMemory isImmediateCharacter: oop) ifTrue:
+ [^(objectMemory characterValueOf: oop) < 256
+ ifTrue:
+ ['=$' , (objectMemory characterValueOf: oop) printString ,
+ ' (' , (String with: (Character value: (objectMemory characterValueOf: oop))) , ')']
+ ifFalse:
+ ['=$' , (objectMemory characterValueOf: oop) printString, '(???)']].
- [^ '=$' , (objectMemory characterValueOf: oop) printString ,
- ' (' , (String with: (Character value: (objectMemory characterValueOf: oop))) , ')'].
  (objectMemory isIntegerObject: oop) ifTrue:
  [^ '=' , (objectMemory integerValueOf: oop) printString ,
  ' (' , (objectMemory integerValueOf: oop) hex , ')'].
  ^'= UNKNOWN IMMEDIATE', ' (' , (objectMemory integerValueOf: oop) hex , ')'].
  (objectMemory addressCouldBeObj: oop) ifFalse:
  [^(oop bitAnd: objectMemory allocationUnit - 1) ~= 0
  ifTrue: [' is misaligned']
  ifFalse: [' is not on the heap']].
  (objectMemory isFreeObject: oop) ifTrue:
  [^' is a free chunk of size ', (objectMemory sizeOfFree: oop) printString].
  (objectMemory isForwarded: oop) ifTrue:
  [^' is a forwarded object to ', (objectMemory followForwarded: oop) hex,
  ' of slot size ', (objectMemory numSlotsOfAny: oop) printString].
  classOop := objectMemory fetchClassOfNonImm: oop.
  (objectMemory numSlotsOf: classOop) = metaclassNumSlots ifTrue:
  [^'class ' , (self nameOfClass: oop)].
  name := self nameOfClass: classOop.
  name size = 0 ifTrue: [name := '??'].
  name = 'String' ifTrue: [^ (self stringOf: oop) printString].
  name = 'ByteString' ifTrue: [^ (self stringOf: oop) printString].
  name = 'Symbol' ifTrue: [^ '#' , (self stringOf: oop)].
  name = 'ByteSymbol' ifTrue: [^ '#' , (self stringOf: oop)].
  name = 'Character' ifTrue: "SpurMemoryManager has immediate Characters; ObjectMemory does not"
  [^ '=' , (Character value: (objectMemory integerValueOf:
  (objectMemory fetchPointer: 0 ofObject: oop))) printString].
  name = 'UndefinedObject' ifTrue: [^ 'nil'].
  name = 'False' ifTrue: [^ 'false'].
  name = 'True' ifTrue: [^ 'true'].
  name = 'Float' ifTrue: [^ '=' , (self dbgFloatValueOf: oop) printString].
  (#('Association' 'ReadOnlyVariableBinding' 'VariableBinding') includes: name) ifTrue:
  [^ '(' ,
  (self shortPrint: (self longAt: oop + BaseHeaderSize)) ,
  ' -> ' ,
  (self longAt: oop + BaseHeaderSize + BytesPerWord) hex8 , ')'].
  ^(('AEIOU' includes: name first) ifTrue: ['an '] ifFalse: ['a ']), name!

Item was changed:
  ----- Method: CogVMSimulator>>utilitiesMenu: (in category 'UI') -----
  utilitiesMenu: aMenuMorph
  aMenuMorph
  add: 'toggle transcript' action: #toggleTranscript;
  add: 'clone VM' action: #cloneSimulation;
  addLine;
  add: 'print ext head frame' action: #printExternalHeadFrame;
  add: 'print int head frame' action: #printHeadFrame;
  add: 'print mc/cog frame' action: [self printFrame: cogit processor fp WithSP: cogit processor sp];
  add: 'short print ext frame & callers' action: [self shortPrintFrameAndCallers: framePointer];
  add: 'short print int frame & callers' action: [self shortPrintFrameAndCallers: localFP];
  add: 'short print mc/cog frame & callers' action: [self shortPrintFrameAndCallers: cogit processor fp];
  add: 'long print ext frame & callers' action: [self printFrameAndCallers: framePointer SP: stackPointer];
  add: 'long print int frame & callers' action: [self printFrameAndCallers: localFP SP: localSP];
  add: 'long print mc/cog frame & callers' action: [self printFrameAndCallers: cogit processor fp SP: cogit processor sp];
  add: 'print frame...' action: [(self promptHex: 'print frame') ifNotNil: [:fp| self printFrame: fp]];
  add: 'print call stack' action: #printCallStack;
  add: 'print stack call stack' action: #printStackCallStack;
  add: 'print call stack of...' action: [(self promptHex: 'context or process oop') ifNotNil: [:obj| self printCallStackOf: obj]];
  add: 'print all stacks' action: #printAllStacks;
  add: 'write back local ptrs' action: [stackPointer := localSP. framePointer := localFP. instructionPointer := localIP.
  self writeBackHeadFramePointers];
  add: 'write back mc ptrs' action: [stackPointer := cogit processor sp. framePointer := cogit processor fp. instructionPointer := cogit processor eip.
  self writeBackHeadFramePointers];
  addLine;
  add: 'print registers' action: [cogit processor printRegistersOn: transcript];
+ add: 'print register map' action: [cogit printRegisterMapOn: transcript];
  add: 'disassemble method/trampoline...' action: [(self promptHex: 'pc') ifNotNil: [:pc| cogit disassembleCodeAt: pc]];
  add: 'disassemble method/trampoline at pc' action: [cogit disassembleCodeAt: cogit processor pc];
  add: 'disassemble ext head frame method' action: [cogit disassembleMethod: (self frameMethod: framePointer)];
  add: 'print oop...' action: [(self promptHex: 'print oop') ifNotNil: [:oop| self printOop: oop]];
  add: 'long print oop...' action: [(self promptHex: 'print oop') ifNotNil: [:oop| self longPrintOop: oop]];
  addLine;
  add: 'inspect object memory' target: objectMemory action: #inspect;
  add: 'inspect cointerpreter' action: #inspect;
  add: 'inspect cogit' target: cogit action: #inspect;
  add: 'inspect method zone' target: cogit methodZone action: #inspect.
  self isThreadedVM ifTrue:
  [aMenuMorph add: 'inspect thread manager' target: self threadManager action: #inspect].
  aMenuMorph
  addLine;
  add: 'print cog methods' target: cogMethodZone action: #printCogMethods;
  add: 'print trampoline table' target: cogit action: #printTrampolineTable;
  add: 'print prim trace log' action: #dumpPrimTraceLog;
  add: 'report recent instructions' target: cogit action: #reportLastNInstructions;
  add: 'set break pc...' action: [(self promptHex: 'break pc') ifNotNil: [:bpc| cogit breakPC: bpc]];
  add: (cogit singleStep
  ifTrue: ['no single step']
  ifFalse: ['single step'])
  action: [cogit singleStep: cogit singleStep not];
  add: (cogit printRegisters
  ifTrue: ['no print registers each instruction']
  ifFalse: ['print registers each instruction'])
  action: [cogit printRegisters: cogit printRegisters not];
  add: (cogit printInstructions
  ifTrue: ['no print instructions each instruction']
  ifFalse: ['print instructions each instruction'])
  action: [cogit printInstructions: cogit printInstructions not];
  addLine;
  add: 'set break count...' action: [|s| s := UIManager default request: 'break count (dec)'.
  s notEmpty ifTrue: [breakCount := Integer readFrom: s readStream]];
  add: 'set break selector...' action: [|s| s := UIManager default request: 'break selector'.
  s notEmpty ifTrue: [self setBreakSelector: s]];
+ add: 'set break block...' action: [|s| s := UIManager default request: 'break block'.
- add: 'set break block...' action: [|s| s := UIManager default request: 'break selector'.
  s notEmpty ifTrue: [self setBreakBlockFromString: s]];
  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 added:
+ ----- Method: Cogit>>printRegisterMapOn: (in category 'disassembly') -----
+ printRegisterMapOn: aStream
+ <doNotGenerate>
+ | map n |
+ map := backEnd generalPurposeRegisterMap.
+ n := 0.
+ map keys sort
+ do: [:regName| | abstractName |
+ abstractName := CogRTLOpcodes nameForRegister: (backEnd abstractRegisterForConcreteRegister: (map at: regName)).
+ aStream nextPutAll: abstractName; nextPutAll: ' => '; nextPutAll: regName]
+ separatedBy: [(n := n + 1) \\ 4 = 0 ifTrue: [aStream cr] ifFalse: [aStream tab]].
+ aStream cr; flush!

Item was changed:
  ----- Method: Cogit>>recordInstruction: (in category 'simulation only') -----
  recordInstruction: thing
  <doNotGenerate>
  lastNInstructions addLast: thing.
  [lastNInstructions size > 160"80"] whileTrue:
  [lastNInstructions removeFirst.
  lastNInstructions size * 2 > lastNInstructions capacity ifTrue:
+ [lastNInstructions makeRoomAtLast]].
+ ^thing!
- [lastNInstructions makeRoomAtLast]]!

Item was changed:
  ----- Method: Cogit>>recordLastInstruction (in category 'simulation only') -----
  recordLastInstruction
  <doNotGenerate>
+ ^self recordInstruction: (processor
- self recordInstruction: (processor
  disassembleNextInstructionIn: coInterpreter memory
  for: (EagerInstructionDecoration ifTrue: [self]))!

Item was changed:
  ----- Method: Cogit>>recordProcessing (in category 'simulation only') -----
  recordProcessing
+ | inst |
  self recordRegisters.
+ inst := self recordLastInstruction.
  printRegisters ifTrue:
  [processor printRegistersOn: coInterpreter transcript].
+ printInstructions ifTrue:
+ [printRegisters ifTrue:
+ [coInterpreter transcript cr].
+ coInterpreter transcript nextPutAll: inst; cr; flush]!
- self recordLastInstruction!

Item was changed:
  ----- Method: Cogit>>simulateCogCodeAt: (in category 'simulation only') -----
  simulateCogCodeAt: address "<Integer>"
  <doNotGenerate>
  | stackZoneBase |
  stackZoneBase := coInterpreter stackZoneBase.
  processor pc: address.
  [[[singleStep ifTrue:
  [[processor sp < stackZoneBase ifTrue: [self halt].
   self recordProcessing.
   (breakPC isInteger
  ifTrue:
  [processor pc = breakPC
  and: [breakBlock value: self]]
  ifFalse:
  [breakBlock value: self]) ifTrue:
  ["printRegisters := printInstructions := true"
  "self reportLastNInstructions"
  "coInterpreter printExternalHeadFrame"
  "coInterpreter printFrameAndCallers: coInterpreter framePointer SP: coInterpreter stackPointer"
  "coInterpreter shortPrintFrameAndCallers: coInterpreter framePointer"
  "coInterpreter printFrame: processor fp WithSP: processor sp"
  "coInterpreter printFrameAndCallers: processor fp SP: processor sp"
  "coInterpreter shortPrintFrameAndCallers: processor fp"
  "self disassembleMethodFor: processor pc"
  coInterpreter changed: #byteCountText.
+ self halt: 'machine code breakpoint at ', processor pc hex]] value]. "So that the Debugger's Over steps over all this"
- self halt: 'machine code breakpoint at ',
- (breakPC isInteger
- ifTrue: [breakPC hex]
- ifFalse: [String streamContents: [:s| breakBlock decompile printOn: s indent: 0]])]] value]. "So that the Debugger's Over steps over all this"
    singleStep
  ifTrue: [processor
  singleStepIn: coInterpreter memory
  minimumAddress: guardPageSize
  readOnlyBelow: methodZone zoneEnd]
  ifFalse: [processor
  runInMemory: coInterpreter memory
  minimumAddress: guardPageSize
  readOnlyBelow: methodZone zoneEnd].
    ((printRegisters or: [printInstructions]) and: [clickConfirm]) ifTrue:
  [(self confirm: 'continue?') ifFalse:
  [self halt]].
    true] whileTrue]
  on: ProcessorSimulationTrap
  do: [:ex| self handleSimulationTrap: ex].
  true] whileTrue!

Item was changed:
  ----- Method: Spur32BitCoMemoryManager>>freeStart: (in category 'cog jit support') -----
  freeStart: aValue
+ self assert: (aValue >= scavenger eden start and: [aValue < scavengeThreshold]).
+ self assert: scavengeThreshold + coInterpreter interpreterAllocationReserveBytes <= scavenger eden limit.
  ^freeStart := aValue!

Item was added:
+ ----- Method: Spur32BitCoMemoryManager>>getScavengeThreshold (in category 'cog jit support') -----
+ getScavengeThreshold
+ <api>
+ <returnTypeC: #usqInt>
+ ^scavengeThreshold!

Item was removed:
- ----- Method: Spur32BitCoMemoryManager>>scavengeThreshold (in category 'cog jit support') -----
- scavengeThreshold
- ^scavengeThreshold!

Item was removed:
- ----- Method: Spur32BitCoMemoryManager>>scavengeThresholdAddress (in category 'trampoline support') -----
- scavengeThresholdAddress
- <api>
- <returnTypeC: #usqInt>
- ^self cCode: [(self addressOf: scavengeThreshold) asUnsignedInteger]
- inSmalltalk: [cogit simulatedReadWriteVariableAddress: #scavengeThreshold in: self]!

Item was changed:
  ----- Method: SpurMemoryManager>>lookupAddress: (in category 'simulation only') -----
  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:
+ [^address = scavengeThreshold ifTrue:
+ ['scavengeThreshold']].
- [^nil].
  address - self baseHeaderSize = hiddenRootsObj ifTrue:
  [^'(hiddenRootsObj+baseHeaderSize)'].
  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: self firstByteFormat and: self firstCompiledMethodFormat - 1) "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 fetchClassOfNonImm: address.
  (class isNil or: [class = nilObj]) ifTrue:
  [^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 numSlotsOf: class) <= (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)) 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: SpurMemoryManager>>printInstancesOf: (in category 'debug printing') -----
+ printInstancesOf: aClassOop
+ "Scan the heap printing the oops of any and all objects that are instances of aClassOop"
+ <api>
+ self printInstancesWithClassIndex: (self rawHashBitsOf: aClassOop)!

Item was added:
+ ----- Method: SpurMemoryManager>>printInstancesWithClassIndex: (in category 'debug printing') -----
+ printInstancesWithClassIndex: classIndex
+ "Scan the heap printing the oops of any and all objects whose classIndex equals the argument."
+ <api>
+ <inline: false>
+ self allHeapEntitiesDo:
+ [:obj|
+ (self classIndexOf: obj) = classIndex ifTrue:
+ [self printHex: obj; cr]]!

Item was changed:
  ----- Method: SpurMemoryManager>>shrinkObjectMemory: (in category 'growing/shrinking memory') -----
  shrinkObjectMemory: delta
  "Attempt to shrink the object memory by the given delta amount."
+ self cCode: [self print: 'shrinkObjectMemory: shouldBeImplemented'; cr]
+ inSmalltalk: [self shouldBeImplemented]!
- self shouldBeImplemented!

Item was changed:
  ----- Method: StackInterpreter>>printMethodCache (in category 'debug printing') -----
  printMethodCache
+ <api>
+ self printMethodCacheFor: -1!
- 0 to: MethodCacheSize - 1 by: MethodCacheEntrySize do:
- [:i | | s c m p |
- s := methodCache at: i + MethodCacheSelector.
- c := methodCache at: i + MethodCacheClass.
- m := methodCache at: i + MethodCacheMethod.
- p := methodCache at: i + MethodCachePrimFunction.
- ((objectMemory addressCouldBeOop: s)
- and: [c ~= 0
- and: [(self addressCouldBeClassObj: c)
- or: [self addressCouldBeClassObj: (objectMemory classForClassTag: c)]]]) ifTrue:
- [self transcript ensureCr.
- self print: i; cr; tab.
- (objectMemory isBytesNonImm: s)
- ifTrue: [self printHex: s; space; print: (self stringOf: s); cr]
- ifFalse: [self shortPrintOop: s].
- self tab.
- (self addressCouldBeClassObj: c)
- ifTrue: [self shortPrintOop: c]
- ifFalse: [self printNum: c; space; shortPrintOop: (objectMemory classForClassTag: c)].
- self tab; shortPrintOop: m; tab.
- p isSymbol
- ifTrue: [self print: p]
- ifFalse: [self printNum: p].
- self cr]]!

Item was added:
+ ----- Method: StackInterpreter>>printMethodCacheFor: (in category 'debug printing') -----
+ printMethodCacheFor: thing
+ <api>
+ 0 to: MethodCacheSize - 1 by: MethodCacheEntrySize do:
+ [:i | | s c m p |
+ s := methodCache at: i + MethodCacheSelector.
+ c := methodCache at: i + MethodCacheClass.
+ m := methodCache at: i + MethodCacheMethod.
+ p := methodCache at: i + MethodCachePrimFunction.
+ ((thing = -1 or: [s = thing or: [c = thing or: [p = thing or: [m = thing
+ or: [(objectMemory addressCouldBeObj: m)
+ and: [(self maybeMethodHasCogMethod: m)
+ and: [(self cogMethodOf: m) asInteger = thing]]]]]]])
+ and: [(objectMemory addressCouldBeOop: s)
+ and: [c ~= 0
+ and: [(self addressCouldBeClassObj: c)
+ or: [self addressCouldBeClassObj: (objectMemory classForClassTag: c)]]]]) ifTrue:
+ [self cCode: [] inSmalltalk: [self transcript ensureCr].
+ self printNum: i; cr; tab.
+ (objectMemory isBytesNonImm: s)
+ ifTrue: [self cCode: 'printf("%x %.*s\n", s, byteLengthOf(s), (char *)firstIndexableField(s))'
+ inSmalltalk: [self printHex: s; space; print: (self stringOf: s); cr]]
+ ifFalse: [self shortPrintOop: s].
+ self tab.
+ (self addressCouldBeClassObj: c)
+ ifTrue: [self shortPrintOop: c]
+ ifFalse: [self printNum: c; space; shortPrintOop: (objectMemory classForClassTag: c)].
+ self tab; shortPrintOop: m; tab.
+ self cCode:
+ [p > 1024
+ ifTrue: [self printHexnp: p]
+ ifFalse: [self printNum: p]]
+ inSmalltalk:
+ [p isSymbol ifTrue: [self print: p] ifFalse: [self printNum: p]].
+ self cr]]!

Item was changed:
  ----- Method: StackInterpreterSimulator>>shortPrint: (in category 'debug support') -----
  shortPrint: oop
  | name classOop |
  (objectMemory isImmediate: oop) ifTrue:
  [(objectMemory isImmediateCharacter: oop) ifTrue:
+ [^(objectMemory characterValueOf: oop) < 256
+ ifTrue:
+ ['=$' , (objectMemory characterValueOf: oop) printString ,
+ ' (' , (String with: (Character value: (objectMemory characterValueOf: oop))) , ')']
+ ifFalse:
+ ['=$' , (objectMemory characterValueOf: oop) printString, '(???)']].
- [^ '=$' , (objectMemory characterValueOf: oop) printString ,
- ' (' , (String with: (Character value: (objectMemory characterValueOf: oop))) , ')'].
  (objectMemory isIntegerObject: oop) ifTrue:
  [^ '=' , (objectMemory integerValueOf: oop) printString ,
  ' (' , (objectMemory integerValueOf: oop) hex , ')'].
  ^'= UNKNOWN IMMEDIATE', ' (' , (objectMemory integerValueOf: oop) hex , ')'].
  (objectMemory addressCouldBeObj: oop) ifFalse:
  [^(oop bitAnd: objectMemory allocationUnit - 1) ~= 0
  ifTrue: [' is misaligned']
  ifFalse: [' is not on the heap']].
  (objectMemory isFreeObject: oop) ifTrue:
  [^' is a free chunk of size ', (objectMemory sizeOfFree: oop) printString].
  (objectMemory isForwarded: oop) ifTrue:
  [^' is a forwarded object to ', (objectMemory followForwarded: oop) hex,
  ' of slot size ', (objectMemory numSlotsOfAny: oop) printString].
  classOop := objectMemory fetchClassOfNonImm: oop.
  classOop ifNil: [^' has a nil class!!!!'].
  (objectMemory numSlotsOf: classOop) = metaclassNumSlots ifTrue:
  [^'class ' , (self nameOfClass: oop)].
  name := self nameOfClass: classOop.
  name size = 0 ifTrue: [name := '??'].
  name = 'String' ifTrue: [^ (self stringOf: oop) printString].
  name = 'ByteString' ifTrue: [^ (self stringOf: oop) printString].
  name = 'Symbol' ifTrue: [^ '#' , (self stringOf: oop)].
  name = 'ByteSymbol' ifTrue: [^ '#' , (self stringOf: oop)].
  name = 'Character' ifTrue: "SpurMemoryManager has immediate Characters; ObjectMemory does not"
  [^ '=' , (Character value: (objectMemory integerValueOf:
  (objectMemory fetchPointer: 0 ofObject: oop))) printString].
  name = 'UndefinedObject' ifTrue: [^ 'nil'].
  name = 'False' ifTrue: [^ 'false'].
  name = 'True' ifTrue: [^ 'true'].
  name = 'Float' ifTrue: [^ '=' , (self dbgFloatValueOf: oop) printString].
  (#('Association' 'ReadOnlyVariableBinding' 'VariableBinding') includes: name) ifTrue:
  [^ '(' ,
  (self shortPrint: (self longAt: oop + BaseHeaderSize)) ,
  ' -> ' ,
  (self longAt: oop + BaseHeaderSize + BytesPerWord) hex8 , ')'].
  ^(('AEIOU' includes: name first) ifTrue: ['an '] ifFalse: ['a ']), name!