A discrepancy between bytecode execution and simulation

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

A discrepancy between bytecode execution and simulation

Christoph Thiede

Hi all, hi Eliot,


I constructed the following code snippet which evaluates to true when running it using the production execution machinery:


nil == thisContext pop


I guess this is fine, because what alternatives would the execution machinery have? It could terminate the whole VM or we could introduce something like #cannotReturn: for invalid stack frame objects. Probably the current implementation is the best despite an invalid position in the context stack has been addressed.


However, the simulation machinery treats the same snippet differently, and it throws:


Error: subscript is out of bounds: 0


I wonder whether it is acceptable to have diverging behaviors for such an ill-defined edge case between simulation and production (btw did I choose the right terms for them? :)). Might it a better alternative to raise a Warning (#notify:) only and then return nil such as the VM appears to do?


Best,

Christoph



Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: A discrepancy between bytecode execution and simulation

Eliot Miranda-2
Hi Christoph,

On Dec 7, 2020, at 9:55 AM, Thiede, Christoph <[hidden email]> wrote:



Hi all, hi Eliot,


I constructed the following code snippet which evaluates to true when running it using the production execution machinery:


nil == thisContext pop


I guess this is fine, because what alternatives would the execution machinery have? It could terminate the whole VM or we could introduce something like #cannotReturn: for invalid stack frame objects. Probably the current implementation is the best despite an invalid position in the context stack has been addressed.


Well, if you evaluated that snippet within some outer stack state I dare say you could generate invalid results.  For example, I would wonder what this does:

    true == (nil == thisContext pop. true)

and this (and the above) will likely generate different effects in the StackInterpreter and the Cog vm, because effectively the Cog JIT preprocesses the bytecodes and executes the code generated from that preprocessing, rather than a literal interpretation of the bytecode.

However, the simulation machinery treats the same snippet differently, and it throws:


Error: subscript is out of bounds: 0


I wonder whether it is acceptable to have diverging behaviors for such an ill-defined edge case between simulation and production (btw did I choose the right terms for them? :)). Might it a better alternative to raise a Warning (#notify:) only and then return nil such as the VM appears to do?

It’s a very good question.  I’m going to provide a very lazy and pragmatic answer, forced by lack of resources to address the issue properly.  It’s clear that the behaviour is at best undefined.  It is good that the simulation produces an error. The only regrettable thing is that what is reported is a low-level error rather than a high-level one that says, fir example, “undefined behaviour encountered”.  Achieving a specification which states that this is undefined behaviour allows the JIT to get away with not dealing with the issue, and that’s important because dealing with the issue such that the JIT could detect this as an error would likely destroy lots of performance gains it is able to make by assuming it is given valid defined execution sequences.

That’s a long winded way of saying that, given limited resources, I’m giving the same response as a doctor that when told by a patient that it hurts when the patient does X says “then stop doing X”.

Best,

Christoph


_,,,^..^,,,_ (phone)


Reply | Threaded
Open this post in threaded view
|

Re: A discrepancy between bytecode execution and simulation

marcel.taeumel
In reply to this post by Christoph Thiede
Hi Christoph

> [...] between simulation and production (btw did I choose the right terms for them? :)

Since code simulation needs code execution, I think that "simulation" is a part of "execution".

Maybe it makes sense to think in terms of "simulation depth"? In a non-debugging scenario, that "simulation depth" is 0 because no simulation code is executed. When you debug/simulate your application code, depth is 1. When you debug/simulate the simulation code, depth is 2. If one would construct deeper "simulate the simulating simulator" processes, depth can be greater than 2. :-)

"Production" is then simulation depth 0. :-D

Best,
Marcel

Am 07.12.2020 18:55:31 schrieb Thiede, Christoph <[hidden email]>:

Hi all, hi Eliot,


I constructed the following code snippet which evaluates to true when running it using the production execution machinery:


nil == thisContext pop


I guess this is fine, because what alternatives would the execution machinery have? It could terminate the whole VM or we could introduce something like #cannotReturn: for invalid stack frame objects. Probably the current implementation is the best despite an invalid position in the context stack has been addressed.


However, the simulation machinery treats the same snippet differently, and it throws:


Error: subscript is out of bounds: 0


I wonder whether it is acceptable to have diverging behaviors for such an ill-defined edge case between simulation and production (btw did I choose the right terms for them? :)). Might it a better alternative to raise a Warning (#notify:) only and then return nil such as the VM appears to do?


Best,

Christoph



Reply | Threaded
Open this post in threaded view
|

Re: A discrepancy between bytecode execution and simulation

Christoph Thiede

Maybe it makes sense to think in terms of "simulation depth"? In a non-debugging scenario, that "simulation depth" is 0 because no simulation code is executed. When you debug/simulate your application code, depth is 1. When you debug/simulate the simulation code, depth is 2. If one would construct deeper "simulate the simulating simulator" processes, depth can be greater than 2. :-)


Yahoo, a Meta-Object Facility adoption for Smalltalk systems. :-) And depth -1 would correspond to the Slang-generated VM implementation, right? ;-)

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Dienstag, 8. Dezember 2020 13:44:09
An: squeak-dev
Betreff: Re: [squeak-dev] A discrepancy between bytecode execution and simulation
 
Hi Christoph

> [...] between simulation and production (btw did I choose the right terms for them? :)

Since code simulation needs code execution, I think that "simulation" is a part of "execution".

Maybe it makes sense to think in terms of "simulation depth"? In a non-debugging scenario, that "simulation depth" is 0 because no simulation code is executed. When you debug/simulate your application code, depth is 1. When you debug/simulate the simulation code, depth is 2. If one would construct deeper "simulate the simulating simulator" processes, depth can be greater than 2. :-)

"Production" is then simulation depth 0. :-D

Best,
Marcel

Am 07.12.2020 18:55:31 schrieb Thiede, Christoph <[hidden email]>:

Hi all, hi Eliot,


I constructed the following code snippet which evaluates to true when running it using the production execution machinery:


nil == thisContext pop


I guess this is fine, because what alternatives would the execution machinery have? It could terminate the whole VM or we could introduce something like #cannotReturn: for invalid stack frame objects. Probably the current implementation is the best despite an invalid position in the context stack has been addressed.


However, the simulation machinery treats the same snippet differently, and it throws:


Error: subscript is out of bounds: 0


I wonder whether it is acceptable to have diverging behaviors for such an ill-defined edge case between simulation and production (btw did I choose the right terms for them? :)). Might it a better alternative to raise a Warning (#notify:) only and then return nil such as the VM appears to do?


Best,

Christoph



Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: A discrepancy between bytecode execution and simulation

Kjell Godo
+1

On Tue, Jan 5, 2021 at 16:30 Thiede, Christoph <[hidden email]> wrote:

Maybe it makes sense to think in terms of "simulation depth"? In a non-debugging scenario, that "simulation depth" is 0 because no simulation code is executed. When you debug/simulate your application code, depth is 1. When you debug/simulate the simulation code, depth is 2. If one would construct deeper "simulate the simulating simulator" processes, depth can be greater than 2. :-)


Yahoo, a Meta-Object Facility adoption for Smalltalk systems. :-) And depth -1 would correspond to the Slang-generated VM implementation, right? ;-)

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Dienstag, 8. Dezember 2020 13:44:09
An: squeak-dev
Betreff: Re: [squeak-dev] A discrepancy between bytecode execution and simulation
 
Hi Christoph

> [...] between simulation and production (btw did I choose the right terms for them? :)

Since code simulation needs code execution, I think that "simulation" is a part of "execution".

Maybe it makes sense to think in terms of "simulation depth"? In a non-debugging scenario, that "simulation depth" is 0 because no simulation code is executed. When you debug/simulate your application code, depth is 1. When you debug/simulate the simulation code, depth is 2. If one would construct deeper "simulate the simulating simulator" processes, depth can be greater than 2. :-)

"Production" is then simulation depth 0. :-D

Best,
Marcel

Am 07.12.2020 18:55:31 schrieb Thiede, Christoph <[hidden email]>:

Hi all, hi Eliot,


I constructed the following code snippet which evaluates to true when running it using the production execution machinery:


nil == thisContext pop


I guess this is fine, because what alternatives would the execution machinery have? It could terminate the whole VM or we could introduce something like #cannotReturn: for invalid stack frame objects. Probably the current implementation is the best despite an invalid position in the context stack has been addressed.


However, the simulation machinery treats the same snippet differently, and it throws:


Error: subscript is out of bounds: 0


I wonder whether it is acceptable to have diverging behaviors for such an ill-defined edge case between simulation and production (btw did I choose the right terms for them? :)). Might it a better alternative to raise a Warning (#notify:) only and then return nil such as the VM appears to do?


Best,

Christoph




Reply | Threaded
Open this post in threaded view
|

Re: A discrepancy between bytecode execution and simulation

codefrau
In reply to this post by Eliot Miranda-2
On Mon, Dec 7, 2020 at 9:12 PM Eliot Miranda <[hidden email]> wrote:

nil == thisContext pop

I guess this is fine, because what alternatives would the execution machinery have? It could terminate the whole VM or we could introduce something like #cannotReturn: for invalid stack frame objects. Probably the current implementation is the best despite an invalid position in the context stack has been addressed.


Well, one pop is almost "fine" because there still is an object on the stack (the receiver). But if you were to do 2 pops then we would fetch from the void.
 
image.png

after stepping over #pop it looks like this

image.png

... when there really should be 2 nils on the stack (in slots 6 and 7). After stepping once more:

image.png

... it actually replaced the receiver slot, going "below" the stack.

However, the simulation machinery treats the same snippet differently, and it throws:

Error: subscript is out of bounds: 0

If we did bounds checking for stack access in SqueakJS (which I used for the above screenshots) then yes we could produce an error. But that would be really expensive.

I wonder whether it is acceptable to have diverging behaviors for such an ill-defined edge case between simulation and production (btw did I choose the right terms for them? :)). Might it a better alternative to raise a Warning (#notify:) only and then return nil such as the VM appears to do?

It’s a very good question.  I’m going to provide a very lazy and pragmatic answer, forced by lack of resources to address the issue properly.  It’s clear that the behaviour is at best undefined.  It is good that the simulation produces an error. The only regrettable thing is that what is reported is a low-level error rather than a high-level one that says, fir example, “undefined behaviour encountered”.  Achieving a specification which states that this is undefined behaviour allows the JIT to get away with not dealing with the issue, and that’s important because dealing with the issue such that the JIT could detect this as an error would likely destroy lots of performance gains it is able to make by assuming it is given valid defined execution sequences.

That’s a long winded way of saying that, given limited resources, I’m giving the same response as a doctor that when told by a patient that it hurts when the patient does X says “then stop doing X”.

Exactly.

Dr. Vanessa 


Reply | Threaded
Open this post in threaded view
|

Re: A discrepancy between bytecode execution and simulation

marcel.taeumel
In reply to this post by Christoph Thiede
Yahoo, a Meta-Object Facility adoption for Smalltalk systems.

There is already a powerful MOP (meta-object protocol) in Squeak/Smalltalk. Take #class etc. Yet, Newspeak's mirrors feel more clean and explicit.

Best,
Marcel

Am 06.01.2021 01:30:13 schrieb Thiede, Christoph <[hidden email]>:

Maybe it makes sense to think in terms of "simulation depth"? In a non-debugging scenario, that "simulation depth" is 0 because no simulation code is executed. When you debug/simulate your application code, depth is 1. When you debug/simulate the simulation code, depth is 2. If one would construct deeper "simulate the simulating simulator" processes, depth can be greater than 2. :-)


Yahoo, a Meta-Object Facility adoption for Smalltalk systems. :-) And depth -1 would correspond to the Slang-generated VM implementation, right? ;-)

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Dienstag, 8. Dezember 2020 13:44:09
An: squeak-dev
Betreff: Re: [squeak-dev] A discrepancy between bytecode execution and simulation
 
Hi Christoph

> [...] between simulation and production (btw did I choose the right terms for them? :)

Since code simulation needs code execution, I think that "simulation" is a part of "execution".

Maybe it makes sense to think in terms of "simulation depth"? In a non-debugging scenario, that "simulation depth" is 0 because no simulation code is executed. When you debug/simulate your application code, depth is 1. When you debug/simulate the simulation code, depth is 2. If one would construct deeper "simulate the simulating simulator" processes, depth can be greater than 2. :-)

"Production" is then simulation depth 0. :-D

Best,
Marcel

Am 07.12.2020 18:55:31 schrieb Thiede, Christoph <[hidden email]>:

Hi all, hi Eliot,


I constructed the following code snippet which evaluates to true when running it using the production execution machinery:


nil == thisContext pop


I guess this is fine, because what alternatives would the execution machinery have? It could terminate the whole VM or we could introduce something like #cannotReturn: for invalid stack frame objects. Probably the current implementation is the best despite an invalid position in the context stack has been addressed.


However, the simulation machinery treats the same snippet differently, and it throws:


Error: subscript is out of bounds: 0


I wonder whether it is acceptable to have diverging behaviors for such an ill-defined edge case between simulation and production (btw did I choose the right terms for them? :)). Might it a better alternative to raise a Warning (#notify:) only and then return nil such as the VM appears to do?


Best,

Christoph