StackInterp/Cog>>transferTo: - assertValidExecutionPointe:r:s differences

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

StackInterp/Cog>>transferTo: - assertValidExecutionPointe:r:s differences

Ben Coman
 
Just curious about the difference in instructionPointer between these two...

StackInterpreter>>transferTo:
     self assertValidExecutionPointe: instructionPointer + 1 r:
framePointer s: stackPointer.


CoIntepreter>>transferTo:from:
    self assertValidExecutionPointe: instructionPointer r:
framePointer s: stackPointer.


cheers -ben
Reply | Threaded
Open this post in threaded view
|

Re: StackInterp/Cog>>transferTo: - assertValidExecutionPointe:r:s differences

Eliot Miranda-2

Hi Ben,

> On Jun 9, 2016, at 6:46 PM, Ben Coman <[hidden email]> wrote:
>
>
> Just curious about the difference in instructionPointer between these two...
>
> StackInterpreter>>transferTo:
>     self assertValidExecutionPointe: instructionPointer + 1 r:
> framePointer s: stackPointer.
>
>
> CoIntepreter>>transferTo:from:
>    self assertValidExecutionPointe: instructionPointer r:
> framePointer s: stackPointer.

The difference is to support richer logging of process switch events in the Cog VM.

In the StackInterpreter context switches only occur in two contexts, within a primitive or checkForEventsMayContextSwitch:.

One might think that the Cog VM is similar but it's much more complicated because a primitive can be invoked in different ways.  One way is from the interpreter via slowPrimitiveResponse, just like the StackInterpreter.  Another way is from a jitted method containing a primitive.  Yet another way is in the attempt to lookup and link a send from machine code that binds to a method with a primitive.  Yet another way is in invoking a primitive in a method that should be interpreted (because it has more literals than the limit for jitting) from machine code.  The VM optimises this transition by using a PIC which can have entries that speed up invoking interpreted methods or MNUs, not just polymorphic sends.

To debug context switch in these contexts (and one more historical context that I think no longer occurs) I needed the richer logging that the from: argument gave me to discover the actual path taken to a process switch.

HTH

>
> cheers -ben
Reply | Threaded
Open this post in threaded view
|

Re: StackInterp/Cog>>transferTo: - assertValidExecutionPointe:r:s differences

Ben Coman

On Fri, Jun 10, 2016 at 11:30 AM, Eliot Miranda <[hidden email]> wrote:

>
> Hi Ben,
>
>> On Jun 9, 2016, at 6:46 PM, Ben Coman <[hidden email]> wrote:
>>
>>
>> Just curious about the difference in instructionPointer between these two...
>>
>> StackInterpreter>>transferTo:
>>     self assertValidExecutionPointe: instructionPointer + 1 r:
>> framePointer s: stackPointer.
>>
>>
>> CoIntepreter>>transferTo:from:
>>    self assertValidExecutionPointe: instructionPointer r:
>> framePointer s: stackPointer.
>
> The difference is to support richer logging of process switch events in the Cog VM.
>
> In the StackInterpreter context switches only occur in two contexts, within a primitive or checkForEventsMayContextSwitch:.
>
> One might think that the Cog VM is similar but it's much more complicated because a primitive can be invoked in different ways.  One way is from the interpreter via slowPrimitiveResponse, just like the StackInterpreter.  Another way is from a jitted method containing a primitive.  Yet another way is in the attempt to lookup and link a send from machine code that binds to a method with a primitive.  Yet another way is in invoking a primitive in a method that should be interpreted (because it has more literals than the limit for jitting) from machine code.  The VM optimises this transition by using a PIC which can have entries that speed up invoking interpreted methods or MNUs, not just polymorphic sends.
>
> To debug context switch in these contexts (and one more historical context that I think no longer occurs) I needed the richer logging that the from: argument gave me to discover the actual path taken to a process switch.


Thanks Eliot.  Great info that I'll file for reference, but this seems
only to describe the addition to Cog of the #from: argument, and I'm
not sure how that relates to my query on why the assert for
StackInterpreter increments the instructionPointer by one, and the
assert for the CoInterpreter does not.  Sorry if my question was too
brief an unclear?

cheers -ben
Reply | Threaded
Open this post in threaded view
|

re: StackInterp/Cog>>transferTo: - assertValidExecutionPointe:r:s differences

Craig Latta
 

     Great info indeed! :)  Eliot, is that in a class comment or a paper
somewhere? I'd like to read the rest of it if so.


     thanks again,

-C

--
Craig Latta
Black Page Digital
Amsterdam
[hidden email]
+31   6 2757 7177 (SMS ok)
+ 1 415  287 3547 (no SMS)

Reply | Threaded
Open this post in threaded view
|

Re: StackInterp/Cog>>transferTo: - assertValidExecutionPointe:r:s differences

Eliot Miranda-2
In reply to this post by Ben Coman

Hi Ben,

    this time I'll try and answer your question rather than my brain fart...

> On Jun 9, 2016, at 6:46 PM, Ben Coman <[hidden email]> wrote:
>
>
> Just curious about the difference in instructionPointer between these two...
>
> StackInterpreter>>transferTo:
>     self assertValidExecutionPointe: instructionPointer + 1 r:
> framePointer s: stackPointer.
>
>
> CoIntepreter>>transferTo:from:
>    self assertValidExecutionPointe: instructionPointer r:
> framePointer s: stackPointer.

In the StackInterpreter, as in the context Interpreter the next bytecode is fetched by pre-incrementing the instructionPointer and then fetching the byte it points to.  Hence it may point to before the first bytecode and hence the + 1 above.  1 is subtracted from a context's pc (2 actually cuz pc is 1-relative and instructionPointer is 0-relative) to derive instructionPointer.

In the Cog VM instructionPointer may also be a machine code pc. So rather than add one, which only makes sense for interpreted methods, the CoInterpreter's assertValidExecutionPointer:s: allows for the - 1 if a frame us interpreted.  The StackInterpreter's method predates the CoInterpreter.

>
>
> cheers -ben

_,,,^..^,,,_ (phone)
Reply | Threaded
Open this post in threaded view
|

re: StackInterp/Cog>>transferTo: - assertValidExecutionPointe:r:s differences

Eliot Miranda-2
In reply to this post by Craig Latta

Hi Craig,


> On Jun 10, 2016, at 12:46 AM, Craig Latta <[hidden email]> wrote:
>
>
>
>     Great info indeed! :)  Eliot, is that in a class comment or a paper
> somewhere? I'd like to read the rest of it if so.

I had planned to write at least a blog post on this and related topics, essentially in how Cog coordinates an interpreter and a JIT, but I've not found time in 5 years :-/. I think it's important to write up.  I remember reading something about the Erlang VM wanting to do the same and they ended up having two separate stacks for interpreted and machine code frames, bad for a number of reasons. The stars may yet align and I'll write it up...

>     thanks again,
>
> -C

_,,,^..^,,,_ (phone)
Reply | Threaded
Open this post in threaded view
|

Re: StackInterp/Cog>>transferTo: - assertValidExecutionPointe:r:s differences

Ben Coman
In reply to this post by Eliot Miranda-2
 


On 10 June 2016 at 20:17, Eliot Miranda <[hidden email]> wrote:
 
Hi Ben,

    this time I'll try and answer your question rather than my brain fart...

> On Jun 9, 2016, at 6:46 PM, Ben Coman <[hidden email]> wrote:
>
>
> Just curious about the difference in instructionPointer between these two...
>
> StackInterpreter>>transferTo:
>     self assertValidExecutionPointe: instructionPointer + 1 r:
> framePointer s: stackPointer.
>
>
> CoIntepreter>>transferTo:from:
>    self assertValidExecutionPointe: instructionPointer r:
> framePointer s: stackPointer.

In the StackInterpreter, as in the context Interpreter the next bytecode is fetched by pre-incrementing the instructionPointer and then fetching the byte it points to.  Hence it may point to before the first bytecode and hence the + 1 above.  1 is subtracted from a context's pc (2 actually cuz pc is 1-relative and instructionPointer is 0-relative) to derive instructionPointer.

In the Cog VM instructionPointer may also be a machine code pc. So rather than add one, which only makes sense for interpreted methods, the CoInterpreter's assertValidExecutionPointer:s: allows for the - 1 if a frame us interpreted.  The StackInterpreter's method predates the CoInterpreter.


I was just wandering in the vicinity of this again, and had a new query...

What is the semantic difference in the naming of the arguments (i.e. lsp<=> lisp  and  lfp<=>lifp)  
between.... ?
StackInterpreter >> assertValidExecutionPointe: lip    r: lfp    s: lsp    imbar: inInterpreter    line: ln 
CoInterpreter     >> assertValidExecutionPointe: lip    r: lifp    s: lisp   imbar: inInterpreter    line: ln

because search/replacing makes it easier to diff the two methods... 

This shows the StackInterpreter method refactored slightly to extract "methodField" variable similar to the CoInterpreter 
making it easier to compare the two, i.e. red-line-16 and green-line-18 are identical, 
but red-line-13 and green-line-14 set "methodField" using different messages, which however have identical definitions.

StackInterpreter >> frameMethod: theFP
<inline: true>
<var: #theFP type: #'char *'>
^stackPages longAt: theFP + FoxMethod

CoInterpreter >> frameMethodField: theFP
<inline: true>
<var: #theFP type: #'char *'>
^stackPages longAt: theFP + FoxMethod

Would it be reasonable to change red-line-13 to send #frameMethodField:  
instead?  Hopefully my slight rearrangement of the asserts in red okay.

cheers -ben



Reply | Threaded
Open this post in threaded view
|

Re: StackInterp/Cog>>transferTo: - assertValidExecutionPointe:r:s differences

Ben Coman
 


On 6 May 2018 at 16:56, Ben Coman <[hidden email]> wrote:


On 10 June 2016 at 20:17, Eliot Miranda <[hidden email]> wrote:
 
Hi Ben,

    this time I'll try and answer your question rather than my brain fart...

> On Jun 9, 2016, at 6:46 PM, Ben Coman <[hidden email]> wrote:
>
>
> Just curious about the difference in instructionPointer between these two...
>
> StackInterpreter>>transferTo:
>     self assertValidExecutionPointe: instructionPointer + 1 r:
> framePointer s: stackPointer.
>
>
> CoIntepreter>>transferTo:from:
>    self assertValidExecutionPointe: instructionPointer r:
> framePointer s: stackPointer.

In the StackInterpreter, as in the context Interpreter the next bytecode is fetched by pre-incrementing the instructionPointer and then fetching the byte it points to.  Hence it may point to before the first bytecode and hence the + 1 above.  1 is subtracted from a context's pc (2 actually cuz pc is 1-relative and instructionPointer is 0-relative) to derive instructionPointer.

In the Cog VM instructionPointer may also be a machine code pc. So rather than add one, which only makes sense for interpreted methods, the CoInterpreter's assertValidExecutionPointer:s: allows for the - 1 if a frame us interpreted.  The StackInterpreter's method predates the CoInterpreter.


I was just wandering in the vicinity of this again, and had a new query...

What is the semantic difference in the naming of the arguments (i.e. lsp<=> lisp  and  lfp<=>lifp)  
between.... ?
StackInterpreter >> assertValidExecutionPointe: lip    r: lfp    s: lsp    imbar: inInterpreter    line: ln 
CoInterpreter     >> assertValidExecutionPointe: lip    r: lifp    s: lisp   imbar: inInterpreter    line: ln

because search/replacing makes it easier to diff the two methods... 

This shows the StackInterpreter method refactored slightly to extract "methodField" variable similar to the CoInterpreter 
making it easier to compare the two, i.e. red-line-16 and green-line-18 are identical, 
but red-line-13 and green-line-14 set "methodField" using different messages, which however have identical definitions.

StackInterpreter >> frameMethod: theFP
<inline: true>
<var: #theFP type: #'char *'>
^stackPages longAt: theFP + FoxMethod

CoInterpreter >> frameMethodField: theFP
<inline: true>
<var: #theFP type: #'char *'>
^stackPages longAt: theFP + FoxMethod

Would it be reasonable to change red-line-13 to send #frameMethodField:  
instead?  Hopefully my slight rearrangement of the asserts in red okay.


========================
I found it a bit convoluted following where CoInterpreter overrides StackInterpreter >> frameIsBlockActivation: 

    StackInterpreter >> frameIsBlockActivation: theFP "<Integer>"
<inline: true>
<var: #theFP type: #'char *'>
^(stackPages byteAt: theFP + FoxFrameFlags + 3) ~= 0

    CoInterpreter >>  frameIsBlockActivation: theFP "<Integer>"
<inline: true>
<var: #theFP type: #'char *'>
^(self isMachineCodeFrame: theFP)
ifTrue: [self mframeIsBlockActivation: theFP]
ifFalse: [self iframeIsBlockActivation: theFP]


But I notice  StackInterpreter >> frameIsBlockActivation: 
is identical to...
    CoInterpreter >> iframeIsBlockActivation: theFP "<Integer>"
<inline: true>
<var: #theFP type: #'char *'>
^(stackPages byteAt: theFP + FoxIFrameFlags + 3) ~= 0

while...
StackInterpreter >> iframeIsBlockActivation: theFP "<Integer>"
^self frameIsBlockActivation: theFP

So reversing StackInterpreter's definitions of these two methods thus...
    StackInterpreter >> iframeIsBlockActivation: theFP "<Integer>"
<inline: true>
<var: #theFP type: #'char *'>
^(stackPages byteAt: theFP + FoxFrameFlags + 3) ~= 0

    StackInterpreter >> frameIsBlockActivation: theFP "<Integer>"
^self iframeIsBlockActivation: theFP

makes the existing CoInterpreter override clearer... 
    CoInterpreter >>  frameIsBlockActivation: theFP "<Integer>"
<inline: true>
<var: #theFP type: #'char *'>
^(self isMachineCodeFrame: theFP)
ifTrue: [self mframeIsBlockActivation: theFP]
ifFalse: [self iframeIsBlockActivation: theFP]

and also CoInterpreter >> iframeIsBlockActivation becomes redundant.

Can I submit a changeset for these?

cheers -ben
Reply | Threaded
Open this post in threaded view
|

Re: StackInterp/Cog>>transferTo: - assertValidExecutionPointe:r:s differences

Eliot Miranda-2
 
Hi Ben,


On May 6, 2018, at 1:58 AM, Ben Coman <[hidden email]> wrote:



On 6 May 2018 at 16:56, Ben Coman <[hidden email]> wrote:


On 10 June 2016 at 20:17, Eliot Miranda <[hidden email]> wrote:
 
Hi Ben,

    this time I'll try and answer your question rather than my brain fart...

> On Jun 9, 2016, at 6:46 PM, Ben Coman <[hidden email]> wrote:
>
>
> Just curious about the difference in instructionPointer between these two...
>
> StackInterpreter>>transferTo:
>     self assertValidExecutionPointe: instructionPointer + 1 r:
> framePointer s: stackPointer.
>
>
> CoIntepreter>>transferTo:from:
>    self assertValidExecutionPointe: instructionPointer r:
> framePointer s: stackPointer.

In the StackInterpreter, as in the context Interpreter the next bytecode is fetched by pre-incrementing the instructionPointer and then fetching the byte it points to.  Hence it may point to before the first bytecode and hence the + 1 above.  1 is subtracted from a context's pc (2 actually cuz pc is 1-relative and instructionPointer is 0-relative) to derive instructionPointer.

In the Cog VM instructionPointer may also be a machine code pc. So rather than add one, which only makes sense for interpreted methods, the CoInterpreter's assertValidExecutionPointer:s: allows for the - 1 if a frame us interpreted.  The StackInterpreter's method predates the CoInterpreter.


I was just wandering in the vicinity of this again, and had a new query...

What is the semantic difference in the naming of the arguments (i.e. lsp<=> lisp  and  lfp<=>lifp)  
between.... ?
StackInterpreter >> assertValidExecutionPointe: lip    r: lfp    s: lsp    imbar: inInterpreter    line: ln 
CoInterpreter     >> assertValidExecutionPointe: lip    r: lifp    s: lisp   imbar: inInterpreter    line: ln

because search/replacing makes it easier to diff the two methods... 

This shows the StackInterpreter method refactored slightly to extract "methodField" variable similar to the CoInterpreter 
making it easier to compare the two, i.e. red-line-16 and green-line-18 are identical, 
but red-line-13 and green-line-14 set "methodField" using different messages, which however have identical definitions.

StackInterpreter >> frameMethod: theFP
<inline: true>
<var: #theFP type: #'char *'>
^stackPages longAt: theFP + FoxMethod

CoInterpreter >> frameMethodField: theFP
<inline: true>
<var: #theFP type: #'char *'>
^stackPages longAt: theFP + FoxMethod

Would it be reasonable to change red-line-13 to send #frameMethodField:  
instead?  Hopefully my slight rearrangement of the asserts in red okay.


========================
I found it a bit convoluted following where CoInterpreter overrides StackInterpreter >> frameIsBlockActivation: 

    StackInterpreter >> frameIsBlockActivation: theFP "<Integer>"
<inline: true>
<var: #theFP type: #'char *'>
^(stackPages byteAt: theFP + FoxFrameFlags + 3) ~= 0

    CoInterpreter >>  frameIsBlockActivation: theFP "<Integer>"
<inline: true>
<var: #theFP type: #'char *'>
^(self isMachineCodeFrame: theFP)
ifTrue: [self mframeIsBlockActivation: theFP]
ifFalse: [self iframeIsBlockActivation: theFP]


But I notice  StackInterpreter >> frameIsBlockActivation: 
is identical to...
    CoInterpreter >> iframeIsBlockActivation: theFP "<Integer>"
<inline: true>
<var: #theFP type: #'char *'>
^(stackPages byteAt: theFP + FoxIFrameFlags + 3) ~= 0

while...
StackInterpreter >> iframeIsBlockActivation: theFP "<Integer>"
^self frameIsBlockActivation: theFP

So reversing StackInterpreter's definitions of these two methods thus...
    StackInterpreter >> iframeIsBlockActivation: theFP "<Integer>"
<inline: true>
<var: #theFP type: #'char *'>
^(stackPages byteAt: theFP + FoxFrameFlags + 3) ~= 0

    StackInterpreter >> frameIsBlockActivation: theFP "<Integer>"
^self iframeIsBlockActivation: theFP

makes the existing CoInterpreter override clearer... 
    CoInterpreter >>  frameIsBlockActivation: theFP "<Integer>"
<inline: true>
<var: #theFP type: #'char *'>
^(self isMachineCodeFrame: theFP)
ifTrue: [self mframeIsBlockActivation: theFP]
ifFalse: [self iframeIsBlockActivation: theFP]

and also CoInterpreter >> iframeIsBlockActivation becomes redundant.

Can I submit a changeset for these?

Thank you, that would be most welcome.  And feel free to include a version of the assert routine that renames lisp & lifp (simple puns) to lsp & lfp or vice verse, as you see fit.


cheers -ben