VM Maker: VMMakerUI-eem.3.mcz

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

VM Maker: VMMakerUI-eem.3.mcz

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

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

Name: VMMakerUI-eem.3
Author: eem
Time: 23 December 2019, 5:27:28.251899 pm
UUID: dc66cff5-f922-4813-82f8-31400bb26941
Ancestors: VMMakerUI-eem.2

Move UI only fiunctionality to VMMakerUI.
Make a hierarchy of VMObjectInspectors.
Expect a VMObjectInspector to respond to open, so that it may be creeated, initialized, and then opened.
Add a proof-of-concept CogAbstractFrameInspector thyat works by parsing the output of printFrame:on:.  This is a daft way of doing things but does prove the concept.  The right way is of courser to refactor frame printing so that it can print on a text stream and add emphasis if desired.

=============== Diff against VMMakerUI-eem.2 ===============

Item was added:
+ CogVMObjectInspector subclass: #CogAbstractFrameInspector
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'VMMakerUI-SqueakInspectors'!

Item was added:
+ ----- Method: CogAbstractFrameInspector>>addressFromString: (in category 'private') -----
+ addressFromString: aString
+ ^(ExtendedNumberParser on: ((ReadStream on: aString) skipSeparators; yourself)) nextInteger!

Item was added:
+ ----- Method: CogAbstractFrameInspector>>buildWith: (in category 'building') -----
+ buildWith: builder
+
+ | windowSpec frameTextSpec |
+ (windowSpec := builder pluggableWindowSpec new)
+ model: self;
+ label: #windowTitle;
+ extent: 400@200;
+ children: OrderedCollection new.
+ (frameTextSpec := builder pluggableTextSpec new)
+ model: self;
+ getText: #text;
+ frame: (0@0 corner: 1@1);
+ yourself.
+ windowSpec children add: frameTextSpec.
+ ^(builder build: windowSpec)
+ paneColor: (coInterpreter ifNotNil: [coInterpreter windowColorToUse] ifNil: [self defaultWindowColor]);
+ yourself!

Item was added:
+ ----- Method: CogAbstractFrameInspector>>evalAttributeForFieldName:framePointer:value:addressString: (in category 'accessing - ui') -----
+ evalAttributeForFieldName: frameField framePointer: framePointer value: valueString addressString: addressString
+ (frameField = 'caller ip'
+ or: [frameField = 'frame ip']) ifTrue:
+ [^PluggableTextAttribute evalBlock: [self interpretFrame: framePointer ip: frameField value: valueString at: (self addressFromString: addressString)]].
+ frameField = 'saved fp' ifTrue:
+ [^PluggableTextAttribute evalBlock: [self interpretFramePointer: frameField value: valueString at: (self addressFromString: addressString)]].
+ frameField = 'method' ifTrue:
+ [^PluggableTextAttribute evalBlock: [self interpretMethod: frameField value: valueString at: (self addressFromString: addressString)]].
+ ^(frameField ~= 'mcfrm flags' and: [frameField ~= 'intfrm flags']) ifTrue:
+ [PluggableTextAttribute evalBlock: [self interpretOop: frameField value: valueString at: (self addressFromString: addressString)]]!

Item was added:
+ ----- Method: CogAbstractFrameInspector>>text (in category 'accessing - ui') -----
+ text
+ ^self textForFramePointer: self framePointer stackPointer: self stackPointer!

Item was added:
+ ----- Method: CogAbstractFrameInspector>>textForFramePointer:stackPointer: (in category 'accessing - ui') -----
+ textForFramePointer: framePointer stackPointer: stackPointer
+ "Print and emphasize the frame text as efficiently as possible, deferring as much interpretation until evaluation time."
+ | frameString frameText |
+ frameText := (String streamContents: [:fs| coInterpreter printFrame: framePointer WithSP: stackPointer on: fs]) allButFirst asText.
+ (frameString := frameText string)
+ findTokens: {Character cr}
+ indicesDo:
+ [:start :stop| | firstColonIndex fieldNameIndex fieldNameEndIndex valueIndex |
+ start = 1
+ ifTrue:
+ [self windowTitle: (frameString copyFrom: 1 to: stop)]
+ ifFalse:
+ [fieldNameIndex := (firstColonIndex := frameString indexOf: $: startingAt: start + 1) + 1.
+ [(frameString at: fieldNameIndex) = Character space] whileTrue:
+ [fieldNameIndex := fieldNameIndex + 1].
+ fieldNameEndIndex := (frameString indexOf: $: startingAt: fieldNameIndex + 1) - 1.
+ valueIndex := fieldNameEndIndex + 2.
+ [(frameString at: valueIndex) = Character space] whileTrue:
+ [valueIndex := valueIndex + 1].
+ (self evalAttributeForFieldName: (frameString copyFrom:  fieldNameIndex to: fieldNameEndIndex)
+ framePointer: framePointer
+ value: (frameString copyFrom: valueIndex to: stop)
+ addressString: (frameString copyFrom: start to: firstColonIndex - 1))
+ ifNotNil:
+ [:attribute| frameText addAttribute: attribute from: fieldNameIndex to: fieldNameEndIndex]]].
+ ^frameText!

Item was added:
+ CogAbstractFrameInspector subclass: #CogFrameInspector
+ instanceVariableNames: 'framePointer stackPointer'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'VMMakerUI-SqueakInspectors'!

Item was added:
+ ----- Method: CogFrameInspector>>framePointer (in category 'accessing') -----
+ framePointer
+
+ ^ framePointer!

Item was added:
+ ----- Method: CogFrameInspector>>framePointer: (in category 'accessing') -----
+ framePointer: anObject
+
+ framePointer := anObject.!

Item was added:
+ ----- Method: CogFrameInspector>>stackPointer (in category 'accessing') -----
+ stackPointer
+
+ ^ stackPointer!

Item was added:
+ ----- Method: CogFrameInspector>>stackPointer: (in category 'accessing') -----
+ stackPointer: anObject
+
+ stackPointer := anObject.!

Item was added:
+ CogAbstractFrameInspector subclass: #CogHeadFrameInspector
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'VMMakerUI-SqueakInspectors'!

Item was changed:
+ CogVMObjectInspector subclass: #CogProcessorAlienInspector
+ instanceVariableNames: 'processor registerSelectors registerCache registerMap'
- Model subclass: #CogProcessorAlienInspector
- instanceVariableNames: 'cogit coInterpreter objectMemory processor registerSelectors windowTitle registerCache registerMap'
  classVariableNames: ''
  poolDictionaries: ''
  category: 'VMMakerUI-SqueakInspectors'!
 
  !CogProcessorAlienInspector commentStamp: 'eem 12/22/2019 08:27' prior: 0!
  A CogProcessorAlienInspector is an inspector for a CogProcessorAlien processor simulator that displays the processor simulator's register state.
 
  Instance Variables
  processor: <CogProcessorAlien>
  registerCache: <Array of Integer>
  registerSelectors: <Array of Symbol>
  windowTitle: <String>!

Item was removed:
- ----- Method: CogProcessorAlienInspector class>>open (in category 'instance creation') -----
- open
- ^ToolBuilder open:
- (self new
- processor: (Cogit classPool at: #ProcessorClass) new;
- yourself)!

Item was removed:
- ----- Method: CogProcessorAlienInspector class>>openFor: (in category 'instance creation') -----
- openFor: aCogit
- ^ToolBuilder open: (self new cogit: aCogit; yourself)!

Item was added:
+ ----- Method: CogProcessorAlienInspector class>>openOn:memory: (in category 'instance creation') -----
+ openOn: aProcessor memory: anArrayOfBits
+ ^ToolBuilder open:
+ (self new
+ processor: aProcessor;
+ memory: anArrayOfBits;
+ yourself)!

Item was changed:
  ----- Method: CogProcessorAlienInspector>>buildWith: (in category 'building') -----
  buildWith: builder
 
+ | windowSpec registerTextSpec |
+ (windowSpec := builder pluggableWindowSpec new)
- | window registers |
- window := builder pluggableWindowSpec new.
- window
  model: self;
  label: #windowTitle;
  extent: 400@200;
  children: OrderedCollection new.
+ (registerTextSpec := builder pluggableTextSpec new)
- registers := builder pluggableTextSpec new.
- registers
  model: self;
  font: Preferences standardFixedFont;
  getText: #text;
  frame: (0@0 corner: 1@1);
  yourself.
+ windowSpec children add: registerTextSpec.
+ ^(builder build: windowSpec)
+ paneColor: (coInterpreter ifNotNil: [coInterpreter windowColorToUse] ifNil: [self defaultWindowColor]);
- window children add: registers.
- ^(builder build: window)
- paneColor: coInterpreter windowColorToUse;
  yourself!

Item was added:
+ ----- Method: CogProcessorAlienInspector>>coInterpreter: (in category 'initialization') -----
+ coInterpreter: aCoInterpreter
+ super coInterpreter: aCoInterpreter.
+ processor := cogit processor.
+ registerSelectors := processor registerStateGetters.
+ self computeRegisterMap.
+ windowTitle := nil.
+ self changed: #text; changed: #window!

Item was changed:
  ----- Method: CogProcessorAlienInspector>>interpret: (in category 'evaluation') -----
  interpret: registerSelector
  "Offer some ways of interpretation."
 
  | value options where choice |
 
  self flag: #updates. "mt: The cache value corresponds maybe to the value at interaction time. In case the register changes quickly and it takes the user some time to make a choice?"
  value := registerCache at: registerSelector.
 
+ coInterpreter
+ ifNil:
+ [options := OrderedDictionary newFrom: {
+ 'Integer' -> #interpret:asInteger:.
+ 'Character' -> #interpret:asCharacter:.
+ 'Machine Instruction' -> #interpret:asInstructionAt:.
+ }.
+ where := self printStringForRegisterContents: value]
+ ifNotNil:
+ [options := OrderedDictionary newFrom: {
+ 'Object' -> #interpret:asObject:.
+ 'Stack frame' -> #interpret:asStackFrame:.
+ 'Code address' -> #interpret:asCodeAddress:.
+ 'Machine Instruction' -> #interpret:asInstructionAt:.
+ 'Integer' -> #interpret:asInteger:.
+ 'Character' -> #interpret:asCharacter:.
+ }.
+ where := coInterpreter whereIs: value].
- options := OrderedDictionary newFrom: {
- 'Object' -> #interpret:asObject:.
- 'Stack frame' -> #interpret:asStackFrame:.
- 'Code address' -> #interpret:asCodeAddress:.
- 'Integer' -> #interpret:asInteger:.
- 'Character' -> #interpret:asCharacter:.
- }.
- where := coInterpreter whereIs: value.
  choice := Project uiManager
  chooseFrom: options keys
  values: options values
  title: ('{1} {2}' format: {registerSelector asUppercase. (where beginsWith: ' ') ifTrue: [where allButFirst] ifFalse: [' = ', where]}).
 
  choice ifNotNil:
  [:selector | self perform: selector with: registerSelector with: value]!

Item was added:
+ ----- Method: CogProcessorAlienInspector>>interpret:asInstructionAt: (in category 'evaluation') -----
+ interpret: registerSelector asInstructionAt: registerValue
+
+ UIManager default inform: registerSelector, ': ', (processor disassembleInstructionAt: registerValue In: memory)!

Item was added:
+ ----- Method: CogProcessorAlienInspector>>memory: (in category 'accessing') -----
+ memory: anArrayOfBits
+ memory := anArrayOfBits!

Item was added:
+ ----- Method: CogProcessorAlienInspector>>printStringForRegisterContents: (in category 'accessing - ui') -----
+ printStringForRegisterContents: value
+ | raw |
+ raw := value printStringBase: (2 raisedTo: self bitsPerDigit) length: processor class wordSize * 8 / self bitsPerDigit padded: true.
+
+ ^(String streamContents:
+ [:s |
+ raw groupsOf: self digitsPerGroup atATimeCollect:
+ [:group |
+ s nextPutAll: group; space]])!

Item was changed:
  ----- Method: CogProcessorAlienInspector>>registerTextAt: (in category 'accessing - ui') -----
  registerTextAt: aRegisterSelector
+ | current last text |
-
- | raw current last text |
  current := processor perform: aRegisterSelector.
  last := registerCache at: aRegisterSelector ifAbsent: [].
  registerCache at: aRegisterSelector put: current.
 
+ text := (self printStringForRegisterContents: current) asText.
- raw := String streamContents:
- [:s |
- current
- printOn: s
- base: (2 raisedTo: self bitsPerDigit)
- length: processor class wordSize * 8 / self bitsPerDigit
- padded: true].
-
- text := (String streamContents:
- [:s |
- raw groupsOf: self digitsPerGroup atATimeCollect:
- [:group |
- s nextPutAll: group; space]])
- asText.
 
  last ~= current ifTrue:
  [text addAllAttributes: {TextEmphasis bold. TextColor color: Color salmon}].
  ^text!

Item was added:
+ VMObjectInspector subclass: #CogVMObjectInspector
+ instanceVariableNames: 'cogit'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'VMMakerUI-SqueakInspectors'!

Item was added:
+ ----- Method: CogVMObjectInspector>>coInterpreter: (in category 'initialization') -----
+ coInterpreter: aCoInterpreter
+ super coInterpreter: aCoInterpreter.
+ cogit := aCoInterpreter cogit!

Item was added:
+ ----- Method: CogVMSimulator>>evaluatePrinter:on: (in category '*VMMakerUI-user interface') -----
+ evaluatePrinter: aBlock on: aStream
+ "Hack to redirect printing to aStream, here to avoid reimplementing all the printing machinery."
+ | savedTraceOn savedTranscript |
+ savedTraceOn := traceOn.
+ savedTranscript := transcript.
+ traceOn := true.
+ transcript := aStream.
+ ^aBlock ensure:
+ [traceOn := savedTraceOn. transcript := savedTranscript]!

Item was added:
+ ----- Method: CogVMSimulator>>printFrame:WithSP:on: (in category '*VMMakerUI-user interface') -----
+ printFrame: theFP WithSP: theSP on: aStream
+ "Hack to print frames on streams, here to avoid reimplementing all the frame printing machinery."
+ ^self
+ evaluatePrinter: [self printFrame: theFP WithSP: theSP]
+ on: aStream!

Item was added:
+ ----- Method: CogVMSimulator>>toggleTranscript (in category '*VMMakerUI-user interface') -----
+ toggleTranscript
+ | transcriptPane |
+ transcript ifNil: [transcript := Transcript. ^self].
+ displayView ifNil: [^self changed: #flash].
+ transcriptPane := (displayView outermostMorphThat: [:m| m isSystemWindow])
+ submorphThat: [:m| m model isStream]
+ ifNone: [^self changed: #flash].
+ transcript := transcript = Transcript
+ ifTrue: [transcriptPane model]
+ ifFalse: [Transcript]!

Item was added:
+ ----- Method: CogVMSimulator>>utilitiesMenu: (in category '*VMMakerUI-user interface') -----
+ utilitiesMenu: aMenuMorph
+ aMenuMorph
+ add: 'toggle transcript' action: #toggleTranscript;
+ add: 'clone VM' action: #cloneSimulationWindow;
+ addLine;
+ add: 'print ext head frame' action: #printExternalHeadFrame;
+ add: 'print int head frame' action: #printHeadFrame;
+ add: 'print mc/cog head frame' action: [self printFrame: cogit processor fp WithSP: cogit processor sp];
+ add: 'short print ext head frame & callers' action: [self shortPrintFrameAndCallers: framePointer];
+ add: 'short print int head frame & callers' action: [self shortPrintFrameAndCallers: localFP];
+ add: 'short print mc/cog head frame & callers' action: [self shortPrintFrameAndCallers: cogit processor fp];
+ add: 'long print ext head frame & callers' action: [self printFrameAndCallers: framePointer SP: stackPointer];
+ add: 'long print int head frame & callers' action: [self printFrameAndCallers: localFP SP: localSP];
+ add: 'long print mc/cog head 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 stack call stack of...' action: [(self promptHex: 'frame') ifNotNil: [:fp| self printStackCallStackOf: fp]];
+ add: 'print call stack of...' action: [(self promptHex: 'context or process oop') ifNotNil: [:obj| self printCallStackOf: obj]];
+ add: 'print call stack of frame...' action: [(self promptHex: 'frame') ifNotNil: [:fp| self printCallStackFP: fp]];
+ 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 pc.
+ self externalWriteBackHeadFramePointers];
+ addLine;
+ add: 'print rump C stack' action: [objectMemory printMemoryFrom: cogit processor sp to: CFramePointer];
+ 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 codeEntryFor: cogit processor pc) isNil
+  and: [(cogit methodZone methodFor: cogit processor pc) = 0])
+ ifTrue: [instructionPointer]
+ ifFalse: [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]];
+ add: 'print context...' action: [(self promptHex: 'print context') ifNotNil: [:oop| self printContext: oop]];
+ add: 'symbolic method...' action: [(self promptHex: 'method bytecodes') ifNotNil: [:oop| self symbolicMethod: oop]];
+ addLine;
+ add: 'inspect object memory' target: objectMemory action: #inspect;
+ add: 'run leak checker' action: [Cursor execute showWhile: [self runLeakChecker]];
+ add: 'inspect cointerpreter' action: #inspect;
+ add: 'inspect cogit' target: cogit action: #inspect;
+ add: 'inspect method zone' target: cogit methodZone action: #inspect;
+ add: 'inspect processor' action: [CogProcessorAlienInspector openFor: self].
+ 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 cog methods with prim...' action:
+ [(self promptNum: 'prim index') ifNotNil: [:pix| cogMethodZone printCogMethodsWithPrimitive: pix]];
+ add: 'print cog methods with selector...' action:
+ [|s| s := UIManager default request: 'selector'.
+ s notEmpty ifTrue:
+ [s = 'nil' ifTrue: [s := nil].
+ cogMethodZone methodsDo:
+ [:m|
+ (s ifNil: [m selector = objectMemory nilObject]
+ ifNotNil: [(objectMemory numBytesOf: m selector) = s size
+ and: [(self strncmp: s
+ _: (m selector + objectMemory baseHeaderSize)
+ _: (objectMemory numBytesOf: m selector)) = 0]]) ifTrue:
+ [cogit printCogMethod: m]]]];
+ add: 'print cog methods with method...' action:
+ [(self promptHex: 'method') ifNotNil: [:methodOop| cogMethodZone printCogMethodsWithMethod: methodOop]];
+ add: 'print cog method for...' action: [(self promptHex: 'pc') ifNotNil: [:pc| cogit printCogMethodFor: pc]];
+ add: 'print cog method header for...' action: [(self promptHex: 'pc') ifNotNil: [:pc| cogit printCogMethodHeaderFor: pc]];
+ add: 'print trampoline table' target: cogit action: #printTrampolineTable;
+ add: 'print prim trace log' action: #dumpPrimTraceLog;
+ add: 'report recent instructions' target: cogit action: #reportLastNInstructions;
+ 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: (cogit singleStep
+ ifTrue: ['no single step']
+ ifFalse: ['single step'])
+ action: [cogit singleStep: cogit singleStep not];
+ add: 'click step' action: [cogit setClickStepBreakBlock];
+ add: 'set break pc', cogit breakPC menuPrompt, '...-ve to disable or remove' action: [cogit promptForBreakPC];
+ 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 (MNU:foo for MNU)'.
+ s notEmpty ifTrue:
+ [(s size > 4 and: [s beginsWith: 'MNU:'])
+ ifTrue: [self setBreakMNUSelector: (s allButFirst: 4)]
+ ifFalse: [self setBreakSelector: s]]];
+ add: 'set break block...' action: [|s| s := UIManager default request: 'break block' initialAnswer: '[:address| false]'.
+ s notEmpty ifTrue: [self setBreakBlockFromString: s]];
+ add: 'set cogit break method...' action: [(self promptHex: 'cogit breakMethod') ifNotNil: [:bm| cogit setBreakMethod: bm]];
+ 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: CogVMSimulator>>windowColorToUse (in category '*VMMakerUI-InterpreterSimulation-Morphic') -----
+ windowColorToUse
+ ^Color lightBlue!

Item was added:
+ ----- Method: Cogit>>setClickStepBreakBlock (in category '*VMMakerUI-user interface') -----
+ setClickStepBreakBlock
+ "Set the break block to present a confirmer, breaking if true, and restoring the previous break block.
+ If an open debugger on the receiver can be found, proceed it."
+ <doNotGenerate>
+ | previousBreakBlock previousAtEachStepBlock previousBreakPC previousSingleStep previousClickConfirm |
+ (breakBlock isNil or: [breakBlock method ~~ thisContext method]) ifTrue:
+ [previousBreakBlock := breakBlock.
+ previousAtEachStepBlock := coInterpreter atEachStepBlock.
+ previousBreakPC := breakPC.
+ previousSingleStep := singleStep.
+ previousClickConfirm := clickConfirm.
+ breakBlock := [:ign|
+ (processor pc ~= previousBreakPC
+ and: [UIManager confirm: 'step?'])
+ ifTrue: [false]
+ ifFalse: [breakBlock := previousBreakBlock.
+ coInterpreter atEachStepBlock: previousAtEachStepBlock.
+ breakPC := previousBreakPC.
+ singleStep := previousSingleStep.
+ clickConfirm := previousClickConfirm.
+ true]].
+ coInterpreter atEachStepBlock:
+ [previousAtEachStepBlock value.
+ (coInterpreter localIP ~= previousBreakPC
+  and: [UIManager confirm: 'step?']) ifFalse:
+ [breakBlock := previousBreakBlock.
+ coInterpreter atEachStepBlock: previousAtEachStepBlock.
+ breakPC := previousBreakPC.
+ singleStep := previousSingleStep.
+ clickConfirm := previousClickConfirm.
+ self halt]].
+ singleStep := breakPC := clickConfirm := true].
+ (World submorphs
+ detect:
+ [:m|
+ m model isDebugger
+ and: [(m model interruptedProcess suspendedContext findContextSuchThat:
+ [:ctxt|
+ (ctxt receiver == self
+ and: [ctxt selector == #simulateCogCodeAt:])
+ or: [ctxt receiver == coInterpreter
+ and: [ctxt selector == #interpret]]]) notNil]]
+ ifNone: []) ifNotNil:
+ [:debuggerWindow|
+ WorldState addDeferredUIMessage:
+ [debuggerWindow model proceed]]!

Item was added:
+ ----- Method: StackInterpreterSimulator>>evaluatePrinter:on: (in category '*VMMakerUI-user interface') -----
+ evaluatePrinter: aBlock on: aStream
+ "Hack to redirect printing to aStream, here to avoid reimplementing all the printing machinery."
+ | savedTraceOn savedTranscript |
+ savedTraceOn := traceOn.
+ savedTranscript := transcript.
+ traceOn := true.
+ transcript := aStream.
+ ^aBlock ensure:
+ [traceOn := savedTraceOn. transcript := savedTranscript]!

Item was added:
+ ----- Method: StackInterpreterSimulator>>printFrame:WithSP:on: (in category '*VMMakerUI-user interface') -----
+ printFrame: theFP WithSP: theSP on: aStream
+ "Hack to print frames on streams, here to avoid reimplementing all the frame printing machinery."
+ ^self
+ evaluatePrinter: [self printFrame: theFP WithSP: theSP]
+ on: aStream!

Item was added:
+ ----- Method: StackInterpreterSimulator>>setClickStepBreakBlock (in category '*VMMakerUI-user interface') -----
+ setClickStepBreakBlock
+ "Set the break block to present a confirmer, breaking if true, and restoring the previous break block.
+ If an open debugger on the receiver can be found, proceed it."
+ <doNotGenerate>
+ | previousAtEachStepBlock |
+ (atEachStepBlock isNil or: [atEachStepBlock method ~~ thisContext method]) ifTrue:
+ [previousAtEachStepBlock := atEachStepBlock.
+ atEachStepBlock :=
+ [previousAtEachStepBlock value.
+ self changed: #byteCountText.
+ (UIManager confirm: 'step?') ifFalse:
+ [atEachStepBlock := previousAtEachStepBlock.
+ self halt]]].
+ (World submorphs
+ detect:
+ [:m|
+ m model isDebugger
+ and: [(m model interruptedProcess suspendedContext findContextSuchThat:
+ [:ctxt|
+ ctxt receiver == self
+ and: [ctxt selector == #run]]) notNil]]
+ ifNone: []) ifNotNil:
+ [:debuggerWindow|
+ WorldState addDeferredUIMessage:
+ [debuggerWindow model proceed]]!

Item was added:
+ ----- Method: StackInterpreterSimulator>>toggleTranscript (in category '*VMMakerUI-user interface') -----
+ toggleTranscript
+ | transcriptPane |
+ transcript ifNil: [transcript := Transcript. ^self].
+ displayView ifNil: [^self changed: #flash].
+ transcriptPane := (displayView outermostMorphThat: [:m| m isSystemWindow])
+ submorphThat: [:m| m model isStream]
+ ifNone: [^self changed: #flash].
+ transcript := transcript = Transcript
+ ifTrue: [transcriptPane model]
+ ifFalse: [Transcript]!

Item was added:
+ ----- Method: StackInterpreterSimulator>>toggleTranscriptForSimulatorMorph: (in category '*VMMakerUI-user interface') -----
+ toggleTranscriptForSimulatorMorph: aTranscriptStreamOrTranscript
+ "tty think this through when not so tired"
+ self flag: 'tty'.
+ transcript ifNil: [transcript := Transcript. ^self].
+ displayView ifNil: [^self changed: #flash].
+ transcript := transcript = Transcript
+ ifTrue: [aTranscriptStreamOrTranscript]
+ ifFalse: [Transcript]!

Item was added:
+ ----- Method: StackInterpreterSimulator>>utilitiesMenu: (in category '*VMMakerUI-user interface') -----
+ utilitiesMenu: aMenuMorph
+ aMenuMorph
+ add: 'toggle transcript' action: #toggleTranscript;
+ add: 'clone VM' action: #cloneSimulationWindow;
+ addLine;
+ add: 'print ext head frame' action: #printExternalHeadFrame;
+ add: 'print int head frame' action: #printHeadFrame;
+ add: 'short print ext frame & callers' action: [self shortPrintFrameAndCallers: framePointer];
+ add: 'short print int frame & callers' action: [self shortPrintFrameAndCallers: localFP];
+ 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: '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 stack call stack of...' action: [(self promptHex: 'frame') ifNotNil: [:fp| self printStackCallStackOf: fp]];
+ add: 'print call stack of...' action: [(self promptHex: 'context or process oop') ifNotNil: [:obj| self printCallStackOf: obj]];
+ add: 'print call stack of frame...' action: [(self promptHex: 'frame') ifNotNil: [:fp| self printCallStackFP: fp]];
+ add: 'print all stacks' action: #printAllStacks;
+ add: 'write back local ptrs' action: [stackPointer := localSP. framePointer := localFP. instructionPointer := localIP.
+ self writeBackHeadFramePointers];
+ add: 'print prim trace log' action: #dumpPrimTraceLog;
+ addLine;
+ 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]];
+ add: 'print context...' action: [(self promptHex: 'print context') ifNotNil: [:oop| self printContext: oop]];
+ addLine;
+ add: 'inspect object memory' target: objectMemory action: #inspect;
+ add: 'run leak checker' action: [Cursor execute showWhile: [self runLeakChecker]];
+ add: 'inspect interpreter' action: #inspect;
+ 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 (MNU:foo for MNU)'.
+ s notEmpty ifTrue:
+ [(s size > 4 and: [s beginsWith: 'MNU:'])
+ ifTrue: [self setBreakMNUSelector: (s allButFirst: 4)]
+ ifFalse: [self setBreakSelector: s]]];
+ add: 'turn valid exec ptrs assert o', (assertVEPAES ifTrue: ['ff'] ifFalse: ['n']) action: [assertVEPAES := assertVEPAES not];
+ add: 'click step' action: [self setClickStepBreakBlock];
+ 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 added:
+ ----- Method: StackInterpreterSimulator>>windowColorToUse (in category '*VMMakerUI-InterpreterSimulation-Morphic') -----
+ windowColorToUse
+ ^Color lightBlue!

Item was changed:
+ Model subclass: #VMObjectInspector
+ instanceVariableNames: 'windowTitle memory coInterpreter objectMemory'
- Inspector subclass: #VMObjectInspector
- instanceVariableNames: 'memory coInterpreter objectMemory cogit'
  classVariableNames: ''
  poolDictionaries: ''
  category: 'VMMakerUI-SqueakInspectors'!

Item was removed:
- ----- Method: VMObjectInspector class>>memory:coInterpreter:objectMemory: (in category 'instance creation') -----
- memory: aByteArray coInterpreter: aStackInterpreter objectMemory: anObjectMemory
- ^self new memory: aByteArray coInterpreter: aStackInterpreter objectMemory: anObjectMemory cogit: nil!

Item was removed:
- ----- Method: VMObjectInspector class>>memory:coInterpreter:objectMemory:cogit: (in category 'instance creation') -----
- memory: aByteArray coInterpreter: aStackInterpreter objectMemory: anObjectMemory cogit: aCogit
- ^self new memory: aByteArray coInterpreter: aStackInterpreter objectMemory: anObjectMemory  cogit: aCogit!

Item was added:
+ ----- Method: VMObjectInspector class>>on: (in category 'instance creation') -----
+ on: aCoInterpreter
+ ^self new coInterpreter: aCoInterpreter; yourself!

Item was added:
+ ----- Method: VMObjectInspector class>>openFor: (in category 'instance creation') -----
+ openFor: aCoInterpreter
+ ^ToolBuilder open: (self new coInterpreter: aCoInterpreter; yourself)!

Item was added:
+ ----- Method: VMObjectInspector>>coInterpreter: (in category 'initialization') -----
+ coInterpreter: aStackInterpreter
+ coInterpreter := aStackInterpreter.
+ objectMemory := aStackInterpreter objectMemory.
+ memory := objectMemory memory!

Item was removed:
- ----- Method: VMObjectInspector>>memory:coInterpreter:objectMemory:cogit: (in category 'initialization') -----
- memory: aByteArray coInterpreter: aStackInterpreter objectMemory: anObjectMemory cogit: aCogit
- memory := aByteArray.
- coInterpreter := aStackInterpreter.
- objectMemory := anObjectMemory.
- cogit := aCogit!

Item was added:
+ ----- Method: VMObjectInspector>>open (in category 'accessing - ui') -----
+ open
+ ^ToolBuilder open: self!

Item was added:
+ ----- Method: VMObjectInspector>>windowTitle (in category 'accessing - ui') -----
+ windowTitle
+
+ ^windowTitle ifNil: [self printString]!

Item was added:
+ ----- Method: VMObjectInspector>>windowTitle: (in category 'accessing - ui') -----
+ windowTitle: newTitle
+
+ windowTitle = newTitle ifFalse:
+ [windowTitle := newTitle.
+ self changed: #windowTitle]!