[Vm-dev] Exploring the simulator (was Re: REPL image for simulation)

Clément Bera bera.clement at gmail.com
Sun Jun 12 08:44:02 UTC 2016


Hi Ben,

I'm glad you're now looking into the JIT. If you have some blog or
something, please write an experience report about you looking into the
simulator. It's helpful for us to have noise around the VM.

On Sun, Jun 12, 2016 at 8:35 AM, Ben Coman <btc at openinworld.com> wrote:

>
> I am stepping for the first time through the CogVM, having [set break
> selector...] forkAt:
> After stepping in a few times I get to #activateCoggedNewMethod.
>   CogVMSimulatorLSB(CoInterpreter)>>dispatchOn:in:
>   CogVMSimulatorLSB(CoInterpreter)>>sendLiteralSelector1ArgBytecode
>   CogVMSimulatorLSB(CoInterpreter)>>commonSendOrdinary
>   CogVMSimulatorLSB(CoInterpreter)>>insternalExecuteNewMethod
>   CogVMSimulatorLSB(CoInterpreter)>>activateCoggedNewMethod
>
> Here from the code at the top.
>     methodHeader := self rawHeaderOf: newMethod.
>     self assert: (self isCogMethodReference: methodHeader).
>     cogMethod := self cCoerceSimple: methodHeader to: #'CogMethod *'.
>     methodHeader := cogMethod methodHeader.
>
> I guess methodHeader's double assignment above is related to the
> machine code frame having two addresses as Clement described...
>

Errr... I don't really fancy the way you say it but I think yes that's it.

A method can have 2 addresses, the address of the bytecoded version in the
heap and the address of its jitted version in the machine code zone. In the
machine code frame printing, the simulator displays the 2 addresses. But
the frame has a single pointer to the method.

So what you're looking at is the dispatch logic from the bytecoded method
to the jitted method. When the JIT compiles a bytecoded method to machine
code, it replaces the bytecoded method compiled method header (first
literal) by a pointer to the jitted version. The machine code version of
the method keeps the compiled method header, so accessing it is different
in methods compiled to machine code and methods not compiled to machine
code.

#rawHeaderOf: answers the first literal of the bytecoded method which is a
pointer to the jitted version of the method if the method has a jitted
version, else is the compiled method header. In the code you show, the VM
ensures the method has a jitted version with the assertion, hence the
compiled method header is fetched from the jitted version.


> >> On Mon, May 30, 2016 at 4:12 PM, Clément Bera <bera.clement at gmail.com>
> wrote:
> >>> Now that you've print the frame, you can see the method addresses in
> this line:
> >>> 16r103144:      method:    16r51578  16r102BDD0 16r102BDD0: a(n)
> CompiledMethod.
> >>> This is a machine code frame, so the method has two addresses:
> >>> 16r51578 => in generated method, so you need to use
> [disassembleMethod/trampoline...] and write down the hex to see the
> disassembly.
> >>> 16r102BDD0 => in the heap. This is the bytecode version of the method.
> You can print it using [print oop...]
>
> This time...
> [print ext head frame] ==>
>   16r101214 M BlockClosure>forkAt: 16r2FC420: a(n) BlockClosure
>   16r101210: method:     16rBBF0  16rC4E948 16rC4E948: a(n) CompiledMethod
>
> self rawHeaderOf: newMethod ==> 16rBBF0
> So the "raw header" is the cogged method.
>
> Looking at the output below, the space ship operator <-> seems to link
> between cogged method headers like a call stack, except   #forkAt:
> calls  #newProcess  which calls  #asContext
>
> [print cog method for...] 16rBBF0 ==>
>   16rBBF0 <-> 16rBC80: method: 16rC4E948 selector: 16r6CC798 forkAt:
>
> [print cog method for...] 16rBC80 ==>
>    16rBC80 <-> 16rBEA8: method: 16rC51970 prim 19 selector: 16r6D1620
> newProcess
>
> [print cog method for...] 16rBEA8 ==>
>    16rBEA8 <->     16rBF28: method:   16rC518C0 selector:   16r76A600
> asContext
>
> However the links don't seem to go back up the call stack but forward,
> to statements to be executed in the future.   So I am confused?
>

Yeah it's the jitted version of the method header address, then <->, then
the jitted method entry point address, the bytecode version address,
selector address.

The cogMethod header is used to store the bytecoded compiled method header
(because it was replaced with a pointer to the cogMethod) and various flags.


>
> -------------
>
> Considering further [print cog method for...] 16rBBF0 ==>
>   16rBBF0 <-> 16rBC80: method: 16rC4E948 selector: 16r6CC798 forkAt:
>
> [print oop...] 16r6CC798 ==>
>    a(n) ByteSymbol nbytes 7  forkAt:
>
> Clement early advised is the bytecode version of the method is this...
> [print oop...] 16rC4E948 ==>
>   16rC4E948: a(n) CompiledMethod nbytes 37
>      16rBBF0  is in generated methods
>    16r6D1620 #newProcess   16r6CC650 #priority:   16r6CC690 #resume
>    16r6CC798 #forkAt:   16rAE5490 a ClassBinding #BlockClosure ->
> 16r0088D618
>   16rC4E968:  70/112 D0/208 88/136 10/16 E1/225 87/135 D2/210 7C/124
>   16rC4E970:  28/40 AF/175 BA/186 F3/243 20/32
>
> Now I've been a bit slow on the uptake and only just realised, but to
> confirm...
> the line 16r6CC798 is the one specifying the method as
> BlockClosure>>forkAt:
>

16r6CC798 is the address of the selector #forkAt:


> For the last two lines, I notice the numbers before the slash (70, 88,
> 10...) are the method bytecode, but what are the numbers after the
> slash?
>

The bytecode in decimal instead of hexa I think.


>
> ----------------
>
> In #activeCoggedNewMethod: the second assignment to methodHeader
>   ==> 16r208000B
>
> which matches the mthhdr field of the raw header
> [print cog method header for...] 16rBBF0 ==>
>     BBF0
>     objhdr: 8000000A000035
>     nArgs: 1 type: 2
>     blksiz: 90
>     method: C4E948
>     mthhdr: 208000B
>     selctr: 6CC798=#forkAt:
>     blkentry: 0
>     stackCheckOffset: 5E/BC4E
>     cmRefersToYoung: no cmIsFullBlock: no
>
> What is "type: 2" ?
>

Haha.

Well when you iterate over the machine code zone you need to know what the
current element you iterate on is. In the machine code zone there can be:
- cog method
- closed PICS
- open PICS
- free space
And now we're adding cog full block method but it's sharing the index with
cog method and have a separated flag :-)

The type tells you what it is. Look at the Literal
variables CMFree, CMClosedPIC, CMOpenPIC, etc .

2 is CMMethod with is a constant. You can improve the printing there and
commit the changes if you feel so.

Ok I have to go I will look at the rest of your mail later.


>
> --------------------------
>
> Stepping through to  Cogit>>ceEnterCogCodePopReceiverReg
> I notice its protocol is "simulation only"
> and it calls  "simulateEnilopmart:numArgs: ceEnterCogCodePopReceiverReg"
> but I don't see any other implementors of #ceEnterCogCodePopReceiverReg.
> Also there is a pragma <doNotGenerate>.
>
> Obviously the real non-simulated VM works differently, but I can't
> determine how.
>
> btw, I have noticed that  ceEnterCogCodePopReceiverReg
>    ==> 16r10B8
> and [print cog method for...] 16r10B8
>    ==> trampoline ceEnterCogCodePopReceiverReg
>
> Is ceEnterCogCodePopReceiverReg provided by the platform C code?
>
> ---------------------------
> Stepping through to simulateCogCodeAt:
> it called processor singleStepIn:minimumAddress:readOnlyBelow:
> which called
> BochsIA32Alien>>primitiveSingleStepInMemory:minimumAddress:readOnlyBelow:
>      <primitive: 'primitiveSingleStepInMemoryMinimumAddressReadWrite'
>        module: 'BochsIA32Plugin'
>        error: ec>
>      ^ec == #'inappropriate operation'
>          ifTrue: [self handleExecutionPrimitiveFailureIn: memoryArray
>                 minimumAddress: minimumAddress]
>          ifFalse: [self reportPrimitiveFailure]
>
> and the debugger cursor was inside the ifTrue: statement.  I found I
> didn't have bochs installed, but after installing bochs-2.6-2, I go
> the same result. So could I get some background around this..
>
> Also I'm curious how the simulator seemed to be running a CogVM before
> bochs was installed. Perhaps since I was not debugging through it, the
> machine code ran for real rather than being simulated.
>
> cheers -ben
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20160612/a2773c3c/attachment-0001.htm


More information about the Vm-dev mailing list