On Wed, Nov 27, 2013 at 2:12 PM, Eliot Miranda <eliot.miranda@gmail.com> wrote:
Hi Phil,

answers in-line.

On Wed, Nov 27, 2013 at 1:34 PM, phil@highoctane.be <phil@highoctane.be> wrote:

I gave it a shot based on the generator.image that PharoVM uses to generate the VM.

But none of :

(| vm |
vm := StackInterpreterSimulator newWithOptions: #().
vm openOn: '/Users/eliot/Cog/startreader.image'.
vm openAsMorph; run)


(| vm |
vm := CogVMSimulator newWithOptions: #(ObjectMemory Spur32BitCoMemoryManager
Cogit StackToRegisterMappingCogit).
vm desiredNumStackPages: 8.
vm objectMemory setCheckForLeaks: 1.
vm openOn: '/Users/eliot/Cog/spurreader.image'.
vm openAsMorph; toggleTranscript; halt; run)

is going to work right away as newWithOptions: isn't there in that image.

If you try and load e.g. VMMaker.oscog-eem.527 into a Squeak trunk image do you get further?  i.e. if you follow the instructions on http://www.mirandabanda.org/cogblog/build-image/ do you get further?
So, there is a initializeWithOptions: #().

When trying out that one, I do get another error.

In fact, the initializeWithOptions: method is wrong:

initializeWithOptions: optionsDictionary
"ObjectMemory initializeWithOptions: Dictionary new"

self initBytesPerWord: (optionsDictionary at: #BytesPerWord ifAbsent: [4]).


the thing is doing #BytesPerWork ifAbsent: ... :-(

Of course, as #() is an Array an not a Dictionary.

So, I tried:

StackInterpreterSimulator initializeWithOptions: Dictionary new.
vm := StackInterpreterSimulator new.

Which got the ball rolling.

But then, of course, same story as here:

Well, based on Clement's comments, I fiddled a bit with the TranscriptStream, which I turned into a simple Transcript and let go of the local image name for the display window.

Also, did 

transcript := Transcript.
displayForm := (ImageMorph fromString: 'Display has not yet been installed') form.

in StackInterpreterSimulator initialize.

So, here is the current stance:

| vm |
StackInterpreterSimulator initializeWithOptions: Dictionary new.
vm := StackInterpreterSimulator new.
vm openOn: 'C:\MinGW\msys\1.0\home\User\pharo\pharo.image'.
vm openAsMorph.
vm run.

the morph opens.

Now, when I do run, I do get a problem in:

InterpreterStackPage>>headFP: pointer

There is an self assert: (pointer = 0 or: [pointer < baseAddress and: [realStackLimit - (LargeContextBytes / 2) <= pointer]]).

And LargeContextBytes is nil.

I looked around for initialization for that one.

It is only in the InterpreterStackPage class >> initialize

Hmmm, that's an initialization order problem.  The code assumes LargeContextSize is initialized first.  It might not be.  I've just changed the code so that it refers to LargeContextSize directly and I've removed LargeContextBytes.  I recommend you do the same. 

So I did;

| vm |
StackInterpreterSimulator initializeWithOptions: Dictionary new.
vm := StackInterpreterSimulator new.
InterpreterStackPage initialize.
vm openOn: 'C:\MinGW\msys\1.0\home\User\pharo\pharo.image'.
vm openAsMorph.
vm run.

Then I got a blinking square running in the top corner.

No amount of stopping processes would interrupt it.

Use the process browser.  That is a good sign.  It is being produced by either StackInterpreterSimulator>>ioRelinquishProcessorForMicroseconds: or CogVMSimulator>>ioRelinquishProcessorForMicroseconds: and means the VM's idle process is running.  Looks like the system is working to some degree.

You'll probably find that a few plugin primitives are failing on start-up, and that the start-up sequence has tried to open a notifier before the GUi is initialized.  In this case I've tried to either a) make the relevant primitives simulate correctly, or b) used an egregious hack to not perform certain initializations.  e.g. in this launch script the initializations of ObjectiveCAlien, ObjectiveCClass et al are not executed in the launch of a Newspeak image:

| cos |
cos := CogVMSimulator newWithOptions: #(NewspeakVM true MULTIPLEBYTECODESETS true Cogit StackToRegisterMappingCogit).
cos desiredNumStackPages: 8.
cos openOn: '/Users/eliot/Newspeak/newsqueakV4/absentSendBug.image'.
cos setBreakSelector: #testNewCompiler.
forShortPrintString: 'class ObjectiveCAlien' filterPerformMessages: #(startUp:);
forShortPrintString: 'class ObjectiveCClass' filterPerformMessages: #(startUp:);
forShortPrintString: 'class BlackMarket' filterPerformMessages: #(startUp:);
forShortPrintString: 'class ThisOSProcess' filterPerformMessages: #(startUp:);

This works by hacking perform in CogVMSimulator.  You'll have to port the code to StackInterpreterSimulator to get it to work there.

So the simulator is running the run loop:

self fetchNextBytecode.
[true] whileTrue:
[self assertValidExecutionPointers.
 atEachStepBlock value. "N.B. may be nil"
 self dispatchOn: currentBytecode in: BytecodeTable.
 self incrementByteCount].

and relinquishing processor every once in a while and this square is shown (Display reverse below] ...

(which is where I end up when interrupting)

ioRelinquishProcessorForMicroseconds: microseconds
"In the simulator give an indication that we're idling and check for input."
Display reverse: (0@0 extent: 16@16).
Sensor peekEvent ifNotNil:
[self forceInterruptCheck].
Processor activeProcess == UIManager default uiProcess ifTrue:
[World doOneCycle].
microseconds >= 1000
ifTrue: [(Delay forMilliseconds: microseconds + 999 // 1000) wait]
ifFalse: [Processor yield]

If one could tell me how to get the display to show, it would be welcome.

The display instVar contains stuff in the debugger but isn't ok to open with something like:

In the transcript, I do see things related to initialization:

(56) Looking for primitiveSetGCBiasToGrowGCLimit in vm
Looking for module  ... not found
(3751) Looking for primitiveFileWrite in FilePlugin
Looking for module FilePlugin
(3751) Looking for secCanCreatePathOfSize in SecurityPlugin
Looking for module SecurityPlugin ... loaded
(3751) Looking for secCanDeletePathOfSize in SecurityPlugin
(3751) Looking for secCanGetFileTypeOfSize in SecurityPlugin
(3751) Looking for secCanListPathOfSize in SecurityPlugin
(3751) Looking for secCanSetFileTypeOfSize in SecurityPlugin
(3751) Looking for secDisableFileAccess in SecurityPlugin
(3751) Looking for secCanDeleteFileOfSize in SecurityPlugin
(3751) Looking for secCanOpenFileOfSizeWritable in SecurityPlugin
(3751) Looking for secCanRenameFileOfSize in SecurityPlugin
(3751) Looking for secHasFileAccess in SecurityPlugin ... loaded
(3774) Looking for primitiveFileSize in FilePlugin
(4390) Looking for primitiveCompareString in MiscPrimitivePlugin
Looking for module MiscPrimitivePlugin ... loaded
(4623) Looking for primitiveDirectoryDelimitor in FilePlugin
(7806) Looking for primitiveIndexOfAsciiInString in MiscPrimitivePlugin
(57216) Looking for primitiveStringHash in MiscPrimitivePlugin
(177977) Looking for primitiveFindFirstInString in MiscPrimitivePlugin
(179055) Looking for primitiveFileOpen in FilePlugin
(179815) Looking for primitiveFileGetPosition in FilePlugin
(179832) Looking for primitiveFileAtEnd in FilePlugin
(179873) Looking for primitiveFileRead in FilePlugin
(182837) Looking for primitiveFileSize in FilePlugin
(182868) Looking for primitiveFileSetPosition in FilePlugin
(186627) Looking for primDigitCompare in LargeIntegers
Looking for module LargeIntegers ... loaded
(186688) Looking for primDigitMultiplyNegative in LargeIntegers
(186884) Looking for primNormalizeNegative in LargeIntegers
(186985) Looking for primDigitAdd in LargeIntegers
(186986) Looking for primNormalizePositive in LargeIntegers
(187038) Looking for primDigitSubtract in LargeIntegers

This is great.  The system's working.
Is there a way to stop the interpreter in order to debug things?

Lots of ways.
1. put a halt before "run", and interact with the VM via the bottom right simulator window's utilities menu to
     a) set a bytecode breakpoint
     b) set a selector breakpoint

2. add or modify methods in the interpreter simulators (StackInterpreterSimulator, CogVMSimulator) or memory simulators (NewObjectMemorySimualtor, NewCoObjectMemorySimulator) to add conditional breakpoints.  e.g. comment-out and modify
Oh, yeah, and something I depend on in debugging the Spur GC is the following:

1. there's a breakpoint in the simulator's fullGC method.  If GC has a bug, run until you hit the breakpoint b4 the relevant GC, then...
2. from the sim's utilities menu choose "clone VM", and in the clone choose "inspect object memory"
3. in the inspector window for the cloned object memory evaluate "fullGC", until yu hit the bug

Rinse and repeat until you fix the GC bug ;-)  Of course this will work with any complex operation whose initial state is difficult to recreate.  Clone and push the clone over the cliff is something I discovered a couple of months ago.  Very handy.

longAt: byteAddress put: a32BitValue
"Note: Adjusted for Smalltalk's 1-based array indexing."
"(byteAddress = 16r183FB00 and: [a32BitValue = 16r3FFFFC]) ifTrue:
[self halt]."
"(byteAddress between: 16r33FBB8 and: 16r33FBCF) ifTrue:
[self halt]."
byteAddress \\ 4 ~= 0 ifTrue: [self unalignedAccessError].
^memory at: byteAddress // 4 + 1 put: a32BitValue

I saw: runAtEachStep: aBlock
self initStackPages.
self loadInitialContext.
self internalizeIPandSP.
self fetchNextBytecode.
[true] whileTrue:
[self assertValidExecutionPointers.
 aBlock value: currentBytecode.
 self dispatchOn: currentBytecode in: BytecodeTable.
 self incrementByteCount].
localIP := localIP - 1.
"undo the pre-increment of IP before returning"
self externalizeIPandSP

How to use that?

You can use the block to do what you want, e.g. collect bytecode stats, compare the stream of bytecodes in a buggy VM with those from a correct VM to find out where they diverge, etc.  But "run" uses the atEachStepBlock, and that is used to implement breakpoints at specific bytecodes or bytecode counts, etc.  See utlitiesMenu: in the interpreter simulators.

Why do I not see the display in the sim?

Dunno.  That you have to fix.  It works in Squeak.
I saw a "quitBlock". What is this about?

It connects the exit routines such as ioExit, ioExitWithErrorCode: to closing of the simulator window.  Browse inst var refs.

In fact, it arranges that the exit routines return from the right place.  So in run and runWithBreakCount: et al it prompts for closing of the simulator window.  Elsewhere it merely returns, e.g. from test.
I am not far from getting this working...

Indeed.  In fact it is already working to a large extent.  Stick with it, you;re nearly there.  Good luck!

Thanks for some clues!

Philippe Back
Dramatic Performance Improvements
Blog: http://philippeback.be | Twitter: @philippeback

High Octane SPRL
rue cour Boisacq 101 | 1301 Bierges | Belgium

Pharo Consortium Member - http://consortium.pharo.org/
Featured on the Software Process and Measurement Cast - http://spamcast.libsyn.com
Sparx Systems Enterprise Architect and Ability Engineering EADocX Value Added Reseller