Two new questions about VM machinery :-)

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

Two new questions about VM machinery :-)

Christoph Thiede

Hi all, hi Eliot,


just for curiosity, I have two new questions about the VM machinery (which are far away from praxis but close to my interests):


1. super on ProtoObject

What would you expect the following to return?

x := Compiler evaluate: 'super identityHash' for: ProtoObject new.

thisContext objectClass: x.

I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.

But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.
If you debug the call instead (Context class >> #runSimulated:), Context >> #send:to:with:lookupIn: raises a nil DNU error, which makes more sense but unfortunately is not consistent with the original VM behavior.
Maybe the Compiler should forbid any call to super from ProtoObject instances at all (more formally: if the receiver's class's superclass is nil)? Or should we adjust the simulation code?
(By the way: If you do the same in Squeak.js, you'll get an infinite recursion :D)

2. Mirror primitives
What is the reason for primitives such as 75 (#identityHash) or 78/139 (#nextInstance/#nextObject) not being mirrored in Context?
Was this simply forgotten, or don't we have the claim to mirror any "essential" primitive without it actually being needed by the simulation machinery?

As always, looking forward to your interesting explanations! :-)

Best,
Christoph


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

Re: Two new questions about VM machinery :-)

Christoph Thiede

>     x := Compiler evaluate: 'super identityHash' for: ProtoObject new.

>     thisContext objectClass: x.

Also interesting:

'super bar' returns a DNU where the receiver is a SmallInteger (sic!). In a second image, the call is skipped, again ...


Von: Squeak-dev <[hidden email]> im Auftrag von Thiede, Christoph
Gesendet: Samstag, 5. September 2020 13:10:29
An: Squeak Dev
Betreff: [squeak-dev] Two new questions about VM machinery :-)
 

Hi all, hi Eliot,


just for curiosity, I have two new questions about the VM machinery (which are far away from praxis but close to my interests):


1. super on ProtoObject

What would you expect the following to return?

x := Compiler evaluate: 'super identityHash' for: ProtoObject new.

thisContext objectClass: x.

I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.

But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.
If you debug the call instead (Context class >> #runSimulated:), Context >> #send:to:with:lookupIn: raises a nil DNU error, which makes more sense but unfortunately is not consistent with the original VM behavior.
Maybe the Compiler should forbid any call to super from ProtoObject instances at all (more formally: if the receiver's class's superclass is nil)? Or should we adjust the simulation code?
(By the way: If you do the same in Squeak.js, you'll get an infinite recursion :D)

2. Mirror primitives
What is the reason for primitives such as 75 (#identityHash) or 78/139 (#nextInstance/#nextObject) not being mirrored in Context?
Was this simply forgotten, or don't we have the claim to mirror any "essential" primitive without it actually being needed by the simulation machinery?

As always, looking forward to your interesting explanations! :-)

Best,
Christoph


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

Re: Two new questions about VM machinery :-)

Tobias Pape
In reply to this post by Christoph Thiede

> On 05.09.2020, at 13:10, Thiede, Christoph <[hidden email]> wrote:
>
> What would you expect the following to return?
> x := Compiler evaluate: 'super identityHash' for: ProtoObject new.
> thisContext objectClass: x.
> I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.
> But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.

No. you're just missing the return, that's why it answers self…
-t

Reply | Threaded
Open this post in threaded view
|

Re: Two new questions about VM machinery :-)

Christoph Thiede

Hi Tobias,


are you sure about that?

[Compiler evaluate: 'self identityHash' for: ProtoObject new] answers a me a SmallInteger. Compiler >> #evaluate:[...] returns the last stack value automatically, just a like a printIt. See senders of #returnSelfIfNoOther: in Parser. :-)


Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Tobias Pape <[hidden email]>
Gesendet: Samstag, 5. September 2020 13:25:26
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 

> On 05.09.2020, at 13:10, Thiede, Christoph <[hidden email]> wrote:
>
> What would you expect the following to return?
> x := Compiler evaluate: 'super identityHash' for: ProtoObject new.
> thisContext objectClass: x.
> I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.
> But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.

No. you're just missing the return, that's why it answers self…
-t



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

Re: Two new questions about VM machinery :-)

Tobias Pape

> On 05.09.2020, at 13:34, Thiede, Christoph <[hidden email]> wrote:
>
> Hi Tobias,
>
> are you sure about that?
> [Compiler evaluate: 'self identityHash' for: ProtoObject new] answers a me a SmallInteger. Compiler >> #evaluate:[...] returns the last stack value automatically, just a like a printIt. See senders of #returnSelfIfNoOther: in Parser. :-)

Ah, I thought it be just a method, I misread that.
That said, 'super' needs a lexical scope, can you do the whole thing in a proper method?
-t

>
> Best,
> Christoph
> Von: Squeak-dev <[hidden email]> im Auftrag von Tobias Pape <[hidden email]>
> Gesendet: Samstag, 5. September 2020 13:25:26
> An: The general-purpose Squeak developers list
> Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
>  
>
> > On 05.09.2020, at 13:10, Thiede, Christoph <[hidden email]> wrote:
> >
> > What would you expect the following to return?
> > x := Compiler evaluate: 'super identityHash' for: ProtoObject new.
> > thisContext objectClass: x.
> > I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.
> > But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.
>
> No. you're just missing the return, that's why it answers self…
> -t



Reply | Threaded
Open this post in threaded view
|

Re: Two new questions about VM machinery :-)

Christoph Thiede

Hi Tobias,


That said, 'super' needs a lexical scope,


Not sure about that either, because [Compiler evaluate: 'super yourself' for: Object new] gives me a MNU (MessageNotUnderstood: ProtoObject>>yourself). A do it block is nothing else than a normal method that is parsed with noPattern (with a default do it selector), isn't it?

But yes, of course:


can you do the whole thing in a proper method?


ProtoObject compile: 'superCallingMethod  ^ super foo'.
ProtoObject new superCallingMethod.
Context runSimulated: [ProtoObject new superCallingMethod]


Same error pattern as described below.

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Tobias Pape <[hidden email]>
Gesendet: Samstag, 5. September 2020 18:59 Uhr
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 

> On 05.09.2020, at 13:34, Thiede, Christoph <[hidden email]> wrote:
>
> Hi Tobias,
>
> are you sure about that?
> [Compiler evaluate: 'self identityHash' for: ProtoObject new] answers a me a SmallInteger. Compiler >> #evaluate:[...] returns the last stack value automatically, just a like a printIt. See senders of #returnSelfIfNoOther: in Parser. :-)

Ah, I thought it be just a method, I misread that.
That said, 'super' needs a lexical scope, can you do the whole thing in a proper method?
-t

>
> Best,
> Christoph
> Von: Squeak-dev <[hidden email]> im Auftrag von Tobias Pape <[hidden email]>
> Gesendet: Samstag, 5. September 2020 13:25:26
> An: The general-purpose Squeak developers list
> Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)

>
> > On 05.09.2020, at 13:10, Thiede, Christoph <[hidden email]> wrote:
> >
> > What would you expect the following to return?
> > x := Compiler evaluate: 'super identityHash' for: ProtoObject new.
> > thisContext objectClass: x.
> > I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.
> > But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.
>
> No. you're just missing the return, that's why it answers self…
> -t





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

Re: Two new questions about VM machinery :-)

Eliot Miranda-2
In reply to this post by Christoph Thiede
Hi Christophe, Hi Tobias,

On Sat, Sep 5, 2020 at 4:10 AM Thiede, Christoph <[hidden email]> wrote:

Hi all, hi Eliot,


just for curiosity, I have two new questions about the VM machinery (which are far away from praxis but close to my interests):


1. super on ProtoObject

What would you expect the following to return?

x := Compiler evaluate: 'super identityHash' for: ProtoObject new.

thisContext objectClass: x.

I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.

My guess before looking at the code was that the send provoked a doesNotUnderstand: and hence the expression returned the result of raising a MessageNotUnderstood exception.  But looking at the code I see that at least in the JIT there is undefined behavior in looking up a message in a nil class (the superclass of ProtoObject is nil).  So thank you for this.  I'll have to firm up the behaviour to ensure a doesNotUnderstand: is the result.

But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.

Which is a bug.  The only reasonable thing to do here (IMO) is for the VM to send doesNotUnderstnnd:.
 
If you debug the call instead (Context class >> #runSimulated:), Context >> #send:to:with:lookupIn: raises a nil DNU error, which makes more sense but unfortunately is not consistent with the original VM behavior.
Maybe the Compiler should forbid any call to super from ProtoObject instances at all (more formally: if the receiver's class's superclass is nil)? Or should we adjust the simulation code?
(By the way: If you do the same in Squeak.js, you'll get an infinite recursion :D)

2. Mirror primitives
What is the reason for primitives such as 75 (#identityHash) or 78/139 (#nextInstance/#nextObject) not being mirrored in Context?
Was this simply forgotten, or don't we have the claim to mirror any "essential" primitive without it actually being needed by the simulation machinery?

They're not needed by the execution simulation machinery.
 
As always, looking forward to your interesting explanations! :-) 


Best,
Christoph

Cheers 

_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: Two new questions about VM machinery :-)

Christoph Thiede

Hi Eliot,


thanks for your answer!


Just to be sure: What class do you intend to lookup #doesNotUnderstand: for if the message not understood's lookupClass is ProtoObject superclass (i.e. nil)? Are you thinking of ProtoObject again? This would break the existing rule "If a message is sent to super but not understood, send #doesNotUnderstand: to super as well" (*), or am I misinterpreting this? Shouldn't you rather signal some special selector in this case?


(*) I'm not sure about this, but I think this results from the Bluebook, page 589. According to the implementation given there, the VM had to crash with a recursion error if a nil class is reached while looking up #doesNotUnderstand:. Because the Bluebook states that the existence of a #doesNotUnderstand: implementation is guaranteed, I would also find it reasonable to have the VM crashed if you actually make a call to super from a method compiled on ProtoObject.


What do you think? :-)


Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Sonntag, 6. September 2020 04:49:54
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 
Hi Christophe, Hi Tobias,

On Sat, Sep 5, 2020 at 4:10 AM Thiede, Christoph <[hidden email]> wrote:

Hi all, hi Eliot,


just for curiosity, I have two new questions about the VM machinery (which are far away from praxis but close to my interests):


1. super on ProtoObject

What would you expect the following to return?

x := Compiler evaluate: 'super identityHash' for: ProtoObject new.

thisContext objectClass: x.

I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.

My guess before looking at the code was that the send provoked a doesNotUnderstand: and hence the expression returned the result of raising a MessageNotUnderstood exception.  But looking at the code I see that at least in the JIT there is undefined behavior in looking up a message in a nil class (the superclass of ProtoObject is nil).  So thank you for this.  I'll have to firm up the behaviour to ensure a doesNotUnderstand: is the result.

But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.

Which is a bug.  The only reasonable thing to do here (IMO) is for the VM to send doesNotUnderstnnd:.
 
If you debug the call instead (Context class >> #runSimulated:), Context >> #send:to:with:lookupIn: raises a nil DNU error, which makes more sense but unfortunately is not consistent with the original VM behavior.
Maybe the Compiler should forbid any call to super from ProtoObject instances at all (more formally: if the receiver's class's superclass is nil)? Or should we adjust the simulation code?
(By the way: If you do the same in Squeak.js, you'll get an infinite recursion :D)

2. Mirror primitives
What is the reason for primitives such as 75 (#identityHash) or 78/139 (#nextInstance/#nextObject) not being mirrored in Context?
Was this simply forgotten, or don't we have the claim to mirror any "essential" primitive without it actually being needed by the simulation machinery?

They're not needed by the execution simulation machinery.
 
As always, looking forward to your interesting explanations! :-) 


Best,
Christoph

Cheers 

_,,,^..^,,,_
best, Eliot


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

Re: Two new questions about VM machinery :-)

Eliot Miranda-2
Hi Christoph,

On Tue, Sep 8, 2020 at 1:34 AM Thiede, Christoph <[hidden email]> wrote:

Hi Eliot,


thanks for your answer!


Just to be sure: What class do you intend to lookup #doesNotUnderstand: for if the message not understood's lookupClass is ProtoObject superclass (i.e. nil)? Are you thinking of ProtoObject again? This would break the existing rule "If a message is sent to super but not understood, send #doesNotUnderstand: to super as well" (*), or am I misinterpreting this? Shouldn't you rather signal some special selector in this case?


Right, it seems asymmetric, but one *has* to lookup in the class of the receiver when doing doesNotUndersatnd:.  For example, imagine one has a special doesNotUnderstand: method.  If a super send causes doesNotUnderstand: but doesn't invoke your special doesNotUnderstand: the system is effectively broken, preventing you from intercepting certain messages.
 

(*) I'm not sure about this, but I think this results from the Bluebook, page 589. According to the implementation given there, the VM had to crash with a recursion error if a nil class is reached while looking up #doesNotUnderstand:. Because the Bluebook states that the existence of a #doesNotUnderstand: implementation is guaranteed, I would also find it reasonable to have the VM crashed if you actually make a call to super from a method compiled on ProtoObject.


That's still the case today. If one removes the doesNotUnderstand: method, or one creates a detached class hierarchy which doesn't contain a doesNotUnderstand: method then the VM will still abort with a recursive doesNotUnderstand: error.  One could add a fall-back, say send a message to thisContext such as object:doesNotUnderstand: . But what's to say one hasn't removed the object:doesNotUnderstand:.  Analogous to Gödel's theorem, if the system is powerful enough to modify itself then it is able to destroy itself.  Dan Ingalls gave a lovely talk at Xerox PARC a few years ago and Donald Knuth was in the audience.  His question to Dan was "With the power to modify the system on the fly, how do you avoid shooting yourself in the foot?". Dan's answer was the same as the Doctor who, when the patient says "Dr, it hurts when I do X",  replies "Don't do X".  Dan simply said "we tend not to, and we have crash recovery tools when we do."

What do you think? :-)


I think that the major difference between the Blue Book's doesNotUndersatnd: and modern doesNotUnderstand: is that if a Message instance has three inst vars then the VM fills in the third inst var with the class in which the message lookup started, so that now in a doesNotUnderstand: method one can find out if the doesNotUnderstand: was the result of a normal send or a super send, and hence a doesNotUnderstand: method has the necessary info if it in fact wanted to do super doesNotUnderstand: for MNUs resulting from super sends.



Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Sonntag, 6. September 2020 04:49:54
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 
Hi Christophe, Hi Tobias,

On Sat, Sep 5, 2020 at 4:10 AM Thiede, Christoph <[hidden email]> wrote:

Hi all, hi Eliot,


just for curiosity, I have two new questions about the VM machinery (which are far away from praxis but close to my interests):


1. super on ProtoObject

What would you expect the following to return?

x := Compiler evaluate: 'super identityHash' for: ProtoObject new.

thisContext objectClass: x.

I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.

My guess before looking at the code was that the send provoked a doesNotUnderstand: and hence the expression returned the result of raising a MessageNotUnderstood exception.  But looking at the code I see that at least in the JIT there is undefined behavior in looking up a message in a nil class (the superclass of ProtoObject is nil).  So thank you for this.  I'll have to firm up the behaviour to ensure a doesNotUnderstand: is the result.

But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.

Which is a bug.  The only reasonable thing to do here (IMO) is for the VM to send doesNotUnderstnnd:.
 
If you debug the call instead (Context class >> #runSimulated:), Context >> #send:to:with:lookupIn: raises a nil DNU error, which makes more sense but unfortunately is not consistent with the original VM behavior.
Maybe the Compiler should forbid any call to super from ProtoObject instances at all (more formally: if the receiver's class's superclass is nil)? Or should we adjust the simulation code?
(By the way: If you do the same in Squeak.js, you'll get an infinite recursion :D)

2. Mirror primitives
What is the reason for primitives such as 75 (#identityHash) or 78/139 (#nextInstance/#nextObject) not being mirrored in Context?
Was this simply forgotten, or don't we have the claim to mirror any "essential" primitive without it actually being needed by the simulation machinery?

They're not needed by the execution simulation machinery.
 
As always, looking forward to your interesting explanations! :-) 


Best,
Christoph

Cheers 

_,,,^..^,,,_
best, Eliot



--
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: Two new questions about VM machinery :-)

Christoph Thiede

Hi Eliot,


this sounds very convincing. If you have patched this in the VM, it would be great if you could send me a link to the relevant patch. :-)


Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Donnerstag, 10. September 2020 07:16:30
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 
Hi Christoph,

On Tue, Sep 8, 2020 at 1:34 AM Thiede, Christoph <[hidden email]> wrote:

Hi Eliot,


thanks for your answer!


Just to be sure: What class do you intend to lookup #doesNotUnderstand: for if the message not understood's lookupClass is ProtoObject superclass (i.e. nil)? Are you thinking of ProtoObject again? This would break the existing rule "If a message is sent to super but not understood, send #doesNotUnderstand: to super as well" (*), or am I misinterpreting this? Shouldn't you rather signal some special selector in this case?


Right, it seems asymmetric, but one *has* to lookup in the class of the receiver when doing doesNotUndersatnd:.  For example, imagine one has a special doesNotUnderstand: method.  If a super send causes doesNotUnderstand: but doesn't invoke your special doesNotUnderstand: the system is effectively broken, preventing you from intercepting certain messages.
 

(*) I'm not sure about this, but I think this results from the Bluebook, page 589. According to the implementation given there, the VM had to crash with a recursion error if a nil class is reached while looking up #doesNotUnderstand:. Because the Bluebook states that the existence of a #doesNotUnderstand: implementation is guaranteed, I would also find it reasonable to have the VM crashed if you actually make a call to super from a method compiled on ProtoObject.


That's still the case today. If one removes the doesNotUnderstand: method, or one creates a detached class hierarchy which doesn't contain a doesNotUnderstand: method then the VM will still abort with a recursive doesNotUnderstand: error.  One could add a fall-back, say send a message to thisContext such as object:doesNotUnderstand: . But what's to say one hasn't removed the object:doesNotUnderstand:.  Analogous to Gödel's theorem, if the system is powerful enough to modify itself then it is able to destroy itself.  Dan Ingalls gave a lovely talk at Xerox PARC a few years ago and Donald Knuth was in the audience.  His question to Dan was "With the power to modify the system on the fly, how do you avoid shooting yourself in the foot?". Dan's answer was the same as the Doctor who, when the patient says "Dr, it hurts when I do X",  replies "Don't do X".  Dan simply said "we tend not to, and we have crash recovery tools when we do."

What do you think? :-)


I think that the major difference between the Blue Book's doesNotUndersatnd: and modern doesNotUnderstand: is that if a Message instance has three inst vars then the VM fills in the third inst var with the class in which the message lookup started, so that now in a doesNotUnderstand: method one can find out if the doesNotUnderstand: was the result of a normal send or a super send, and hence a doesNotUnderstand: method has the necessary info if it in fact wanted to do super doesNotUnderstand: for MNUs resulting from super sends.



Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Sonntag, 6. September 2020 04:49:54
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 
Hi Christophe, Hi Tobias,

On Sat, Sep 5, 2020 at 4:10 AM Thiede, Christoph <[hidden email]> wrote:

Hi all, hi Eliot,


just for curiosity, I have two new questions about the VM machinery (which are far away from praxis but close to my interests):


1. super on ProtoObject

What would you expect the following to return?

x := Compiler evaluate: 'super identityHash' for: ProtoObject new.

thisContext objectClass: x.

I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.

My guess before looking at the code was that the send provoked a doesNotUnderstand: and hence the expression returned the result of raising a MessageNotUnderstood exception.  But looking at the code I see that at least in the JIT there is undefined behavior in looking up a message in a nil class (the superclass of ProtoObject is nil).  So thank you for this.  I'll have to firm up the behaviour to ensure a doesNotUnderstand: is the result.

But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.

Which is a bug.  The only reasonable thing to do here (IMO) is for the VM to send doesNotUnderstnnd:.
 
If you debug the call instead (Context class >> #runSimulated:), Context >> #send:to:with:lookupIn: raises a nil DNU error, which makes more sense but unfortunately is not consistent with the original VM behavior.
Maybe the Compiler should forbid any call to super from ProtoObject instances at all (more formally: if the receiver's class's superclass is nil)? Or should we adjust the simulation code?
(By the way: If you do the same in Squeak.js, you'll get an infinite recursion :D)

2. Mirror primitives
What is the reason for primitives such as 75 (#identityHash) or 78/139 (#nextInstance/#nextObject) not being mirrored in Context?
Was this simply forgotten, or don't we have the claim to mirror any "essential" primitive without it actually being needed by the simulation machinery?

They're not needed by the execution simulation machinery.
 
As always, looking forward to your interesting explanations! :-) 


Best,
Christoph

Cheers 

_,,,^..^,,,_
best, Eliot



--
_,,,^..^,,,_
best, Eliot


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

Re: Two new questions about VM machinery :-)

Eliot Miranda-2
Hi Christoph,

On Fri, Sep 11, 2020 at 3:31 AM Thiede, Christoph <[hidden email]> wrote:

Hi Eliot,

this sounds very convincing. If you have patched this in the VM, it would be great if you could send me a link to the relevant patch. :-)


Once I fix the issue?  Or where the extra info in the Message object is filled in? 

Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Donnerstag, 10. September 2020 07:16:30
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 
Hi Christoph,

On Tue, Sep 8, 2020 at 1:34 AM Thiede, Christoph <[hidden email]> wrote:

Hi Eliot,


thanks for your answer!


Just to be sure: What class do you intend to lookup #doesNotUnderstand: for if the message not understood's lookupClass is ProtoObject superclass (i.e. nil)? Are you thinking of ProtoObject again? This would break the existing rule "If a message is sent to super but not understood, send #doesNotUnderstand: to super as well" (*), or am I misinterpreting this? Shouldn't you rather signal some special selector in this case?


Right, it seems asymmetric, but one *has* to lookup in the class of the receiver when doing doesNotUndersatnd:.  For example, imagine one has a special doesNotUnderstand: method.  If a super send causes doesNotUnderstand: but doesn't invoke your special doesNotUnderstand: the system is effectively broken, preventing you from intercepting certain messages.
 

(*) I'm not sure about this, but I think this results from the Bluebook, page 589. According to the implementation given there, the VM had to crash with a recursion error if a nil class is reached while looking up #doesNotUnderstand:. Because the Bluebook states that the existence of a #doesNotUnderstand: implementation is guaranteed, I would also find it reasonable to have the VM crashed if you actually make a call to super from a method compiled on ProtoObject.


That's still the case today. If one removes the doesNotUnderstand: method, or one creates a detached class hierarchy which doesn't contain a doesNotUnderstand: method then the VM will still abort with a recursive doesNotUnderstand: error.  One could add a fall-back, say send a message to thisContext such as object:doesNotUnderstand: . But what's to say one hasn't removed the object:doesNotUnderstand:.  Analogous to Gödel's theorem, if the system is powerful enough to modify itself then it is able to destroy itself.  Dan Ingalls gave a lovely talk at Xerox PARC a few years ago and Donald Knuth was in the audience.  His question to Dan was "With the power to modify the system on the fly, how do you avoid shooting yourself in the foot?". Dan's answer was the same as the Doctor who, when the patient says "Dr, it hurts when I do X",  replies "Don't do X".  Dan simply said "we tend not to, and we have crash recovery tools when we do."

What do you think? :-)


I think that the major difference between the Blue Book's doesNotUndersatnd: and modern doesNotUnderstand: is that if a Message instance has three inst vars then the VM fills in the third inst var with the class in which the message lookup started, so that now in a doesNotUnderstand: method one can find out if the doesNotUnderstand: was the result of a normal send or a super send, and hence a doesNotUnderstand: method has the necessary info if it in fact wanted to do super doesNotUnderstand: for MNUs resulting from super sends.



Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Sonntag, 6. September 2020 04:49:54
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 
Hi Christophe, Hi Tobias,

On Sat, Sep 5, 2020 at 4:10 AM Thiede, Christoph <[hidden email]> wrote:

Hi all, hi Eliot,


just for curiosity, I have two new questions about the VM machinery (which are far away from praxis but close to my interests):


1. super on ProtoObject

What would you expect the following to return?

x := Compiler evaluate: 'super identityHash' for: ProtoObject new.

thisContext objectClass: x.

I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.

My guess before looking at the code was that the send provoked a doesNotUnderstand: and hence the expression returned the result of raising a MessageNotUnderstood exception.  But looking at the code I see that at least in the JIT there is undefined behavior in looking up a message in a nil class (the superclass of ProtoObject is nil).  So thank you for this.  I'll have to firm up the behaviour to ensure a doesNotUnderstand: is the result.

But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.

Which is a bug.  The only reasonable thing to do here (IMO) is for the VM to send doesNotUnderstnnd:.
 
If you debug the call instead (Context class >> #runSimulated:), Context >> #send:to:with:lookupIn: raises a nil DNU error, which makes more sense but unfortunately is not consistent with the original VM behavior.
Maybe the Compiler should forbid any call to super from ProtoObject instances at all (more formally: if the receiver's class's superclass is nil)? Or should we adjust the simulation code?
(By the way: If you do the same in Squeak.js, you'll get an infinite recursion :D)

2. Mirror primitives
What is the reason for primitives such as 75 (#identityHash) or 78/139 (#nextInstance/#nextObject) not being mirrored in Context?
Was this simply forgotten, or don't we have the claim to mirror any "essential" primitive without it actually being needed by the simulation machinery?

They're not needed by the execution simulation machinery.
 
As always, looking forward to your interesting explanations! :-) 


Best,
Christoph

Cheers 

_,,,^..^,,,_
best, Eliot



--
_,,,^..^,,,_
best, Eliot



--
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: Two new questions about VM machinery :-)

Christoph Thiede

Once you fixed the issue :-)


Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Freitag, 11. September 2020 19:12:36
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 
Hi Christoph,

On Fri, Sep 11, 2020 at 3:31 AM Thiede, Christoph <[hidden email]> wrote:

Hi Eliot,

this sounds very convincing. If you have patched this in the VM, it would be great if you could send me a link to the relevant patch. :-)


Once I fix the issue?  Or where the extra info in the Message object is filled in? 

Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Donnerstag, 10. September 2020 07:16:30
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 
Hi Christoph,

On Tue, Sep 8, 2020 at 1:34 AM Thiede, Christoph <[hidden email]> wrote:

Hi Eliot,


thanks for your answer!


Just to be sure: What class do you intend to lookup #doesNotUnderstand: for if the message not understood's lookupClass is ProtoObject superclass (i.e. nil)? Are you thinking of ProtoObject again? This would break the existing rule "If a message is sent to super but not understood, send #doesNotUnderstand: to super as well" (*), or am I misinterpreting this? Shouldn't you rather signal some special selector in this case?


Right, it seems asymmetric, but one *has* to lookup in the class of the receiver when doing doesNotUndersatnd:.  For example, imagine one has a special doesNotUnderstand: method.  If a super send causes doesNotUnderstand: but doesn't invoke your special doesNotUnderstand: the system is effectively broken, preventing you from intercepting certain messages.
 

(*) I'm not sure about this, but I think this results from the Bluebook, page 589. According to the implementation given there, the VM had to crash with a recursion error if a nil class is reached while looking up #doesNotUnderstand:. Because the Bluebook states that the existence of a #doesNotUnderstand: implementation is guaranteed, I would also find it reasonable to have the VM crashed if you actually make a call to super from a method compiled on ProtoObject.


That's still the case today. If one removes the doesNotUnderstand: method, or one creates a detached class hierarchy which doesn't contain a doesNotUnderstand: method then the VM will still abort with a recursive doesNotUnderstand: error.  One could add a fall-back, say send a message to thisContext such as object:doesNotUnderstand: . But what's to say one hasn't removed the object:doesNotUnderstand:.  Analogous to Gödel's theorem, if the system is powerful enough to modify itself then it is able to destroy itself.  Dan Ingalls gave a lovely talk at Xerox PARC a few years ago and Donald Knuth was in the audience.  His question to Dan was "With the power to modify the system on the fly, how do you avoid shooting yourself in the foot?". Dan's answer was the same as the Doctor who, when the patient says "Dr, it hurts when I do X",  replies "Don't do X".  Dan simply said "we tend not to, and we have crash recovery tools when we do."

What do you think? :-)


I think that the major difference between the Blue Book's doesNotUndersatnd: and modern doesNotUnderstand: is that if a Message instance has three inst vars then the VM fills in the third inst var with the class in which the message lookup started, so that now in a doesNotUnderstand: method one can find out if the doesNotUnderstand: was the result of a normal send or a super send, and hence a doesNotUnderstand: method has the necessary info if it in fact wanted to do super doesNotUnderstand: for MNUs resulting from super sends.



Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Sonntag, 6. September 2020 04:49:54
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] Two new questions about VM machinery :-)
 
Hi Christophe, Hi Tobias,

On Sat, Sep 5, 2020 at 4:10 AM Thiede, Christoph <[hidden email]> wrote:

Hi all, hi Eliot,


just for curiosity, I have two new questions about the VM machinery (which are far away from praxis but close to my interests):


1. super on ProtoObject

What would you expect the following to return?

x := Compiler evaluate: 'super identityHash' for: ProtoObject new.

thisContext objectClass: x.

I would have guessed that either the VM crashes or ProtoObject >> #cannotInterpret: is called.

My guess before looking at the code was that the send provoked a doesNotUnderstand: and hence the expression returned the result of raising a MessageNotUnderstood exception.  But looking at the code I see that at least in the JIT there is undefined behavior in looking up a message in a nil class (the superclass of ProtoObject is nil).  So thank you for this.  I'll have to firm up the behaviour to ensure a doesNotUnderstand: is the result.

But actually, it answers you the ProtoObject instance, which I find very interesting because it means that if a message cannot be looked up, it is simply and silently skipped.

Which is a bug.  The only reasonable thing to do here (IMO) is for the VM to send doesNotUnderstnnd:.
 
If you debug the call instead (Context class >> #runSimulated:), Context >> #send:to:with:lookupIn: raises a nil DNU error, which makes more sense but unfortunately is not consistent with the original VM behavior.
Maybe the Compiler should forbid any call to super from ProtoObject instances at all (more formally: if the receiver's class's superclass is nil)? Or should we adjust the simulation code?
(By the way: If you do the same in Squeak.js, you'll get an infinite recursion :D)

2. Mirror primitives
What is the reason for primitives such as 75 (#identityHash) or 78/139 (#nextInstance/#nextObject) not being mirrored in Context?
Was this simply forgotten, or don't we have the claim to mirror any "essential" primitive without it actually being needed by the simulation machinery?

They're not needed by the execution simulation machinery.
 
As always, looking forward to your interesting explanations! :-) 


Best,
Christoph

Cheers 

_,,,^..^,,,_
best, Eliot



--
_,,,^..^,,,_
best, Eliot



--
_,,,^..^,,,_
best, Eliot


Carpe Squeak!