[Vm-dev] Exploring the simulator (was Re: REPL image for
simulation)
Ben Coman
btc at openinworld.com
Sun Jun 12 06:35:18 UTC 2016
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...
>> 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?
-------------
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:
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?
----------------
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" ?
--------------------------
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
More information about the Vm-dev
mailing list