Can we override == in Pharo ?
Hello, here I have a class A>>== ^ true Now: a := A new. b := A new. a == b "Answers false" a perform: #== with: b "Answers true" Do I have to remove the usage of the byte code for #== in the compiler to be able to override == ?
2014/1/6 Clément Bera <bera.clement@gmail.com>
Hello,
here I have a class
A>>== ^ true
Now: a := A new. b := A new. a == b "Answers false" a perform: #== with: b "Answers true"
Do I have to remove the usage of the byte code for #== in the compiler to be able to override == ?
No, a==b should be used for "are the same Objects" (pointing to the same object) and not "are equal". Look for example at the commentn for ProtoObject>>== Nicolai
On 6 January 2014 11:11, Nicolai Hess <nicolaihess@web.de> wrote:
2014/1/6 Clément Bera <bera.clement@gmail.com>
Hello,
here I have a class
A>>== ^ true
Now: a := A new. b := A new. a == b "Answers false" a perform: #== with: b "Answers true"
Do I have to remove the usage of the byte code for #== in the compiler to be able to override == ?
No, a==b should be used for "are the same Objects" (pointing to the same object) and not "are equal". Look for example at the commentn for ProtoObject>>==
Given the kinds of things Clément does, I suspect he knows full well the difference between #== and #=. My understanding is that the compiler inlines #== sends like it does with #timesRepeat: and ifTrue:ifFalse:. So yes, you'd need to fiddle with the compiler for any #== overrides to actually run. (I'm keen for Marcus to show us how exactly to do that in Opal!) frank
Nicolai
So I tried and it worked. In Opal to remove the usage of #==, I removed it from the special selector array in the method: IRBytecodeGenerator class>>specialSelectorsArray ^ #(#+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 nil 0 #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0) Then I ran: IRBytecodeGenerator initialize. OpalCompiler recompileAll. Then in my example: A>>== ^ true a := A new. b := A new. a == b answered true, so it worked. I don't like all these messages with no lookup. I don't even know if this permits to earn performance now that we have inline caches. @Frank Shearar Just a detail, #timesRepeat: is not inlined any more by default in Pharo 3.0 because there were conflicts with a stream library. Anyway it didn't provide a lot of performance (just removed 1 indirection). 2014/1/6 Frank Shearar <frank.shearar@gmail.com>
On 6 January 2014 11:11, Nicolai Hess <nicolaihess@web.de> wrote:
2014/1/6 Clément Bera <bera.clement@gmail.com>
Hello,
here I have a class
A>>== ^ true
Now: a := A new. b := A new. a == b "Answers false" a perform: #== with: b "Answers true"
Do I have to remove the usage of the byte code for #== in the compiler
to
be able to override == ?
No, a==b should be used for "are the same Objects" (pointing to the same object) and not "are equal". Look for example at the commentn for ProtoObject>>==
Given the kinds of things Clément does, I suspect he knows full well the difference between #== and #=.
My understanding is that the compiler inlines #== sends like it does with #timesRepeat: and ifTrue:ifFalse:. So yes, you'd need to fiddle with the compiler for any #== overrides to actually run.
(I'm keen for Marcus to show us how exactly to do that in Opal!)
frank
Nicolai
On 06 Jan 2014, at 13:43, Clément Bera <bera.clement@gmail.com> wrote:
So I tried and it worked.
In Opal to remove the usage of #==, I removed it from the special selector array in the method: IRBytecodeGenerator class>>specialSelectorsArray ^ #(#+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 nil 0 #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0)
Then I ran: IRBytecodeGenerator initialize. OpalCompiler recompileAll.
Then in my example:
A>>== ^ true
a := A new. b := A new. a == b answered true, so it worked.
The only side effect it can have is that people might have written code with the knowledge that sending #== can not lead to an interrupt check, e.g. a GC happening or process switching. Marcus
On 6 janv. 2014, at 13:55, Marcus Denker <marcus.denker@inria.fr> wrote:
On 06 Jan 2014, at 13:43, Clément Bera <bera.clement@gmail.com> wrote:
So I tried and it worked.
In Opal to remove the usage of #==, I removed it from the special selector array in the method: IRBytecodeGenerator class>>specialSelectorsArray ^ #(#+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 nil 0 #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0)
Then I ran: IRBytecodeGenerator initialize. OpalCompiler recompileAll.
Then in my example:
A>>== ^ true
a := A new. b := A new. a == b answered true, so it worked.
The only side effect it can have is that people might have written code with the knowledge that sending #== can not lead to an interrupt check, e.g. a GC happening or process switching.
Yes for example in #~~
Marcus
Hi Clement, On Mon, Jan 6, 2014 at 4:42 AM, Clément Bera <bera.clement@gmail.com> wrote:
So I tried and it worked.
In Opal to remove the usage of #==, I removed it from the special selector array in the method: IRBytecodeGenerator class>>specialSelectorsArray ^ #(#+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 nil 0 #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0)
Then I ran: IRBytecodeGenerator initialize. OpalCompiler recompileAll.
Then in my example:
A>>== ^ true
a := A new. b := A new. a == b answered true, so it worked.
I don't like all these messages with no lookup. I don't even know if this permits to earn performance now that we have inline caches.
Well, the arithmetic selectors *really* pay their way. Try your experiment with #+ through #~= and I bet you'll see slower loops. I think there's a compromise, which is to only inline the arithmetic selectors. That's what we did with the VisualWorks VM, HPS. There one can set a hidden flag in the image which directs the JIT (HPS only has a JIT) not to inline #== (VW does not inline #class), and change the flag with a primitive. We could (and I think should) do the same. Note that currently only #== and #class are inlined for all objects. The arithmetic selectors #+ et al and #< et al are only inlined by the JIT for SmallInteger, and executed without lookup in the interpreter for SmallInteger x Float.
@Frank Shearar Just a detail, #timesRepeat: is not inlined any more by default in Pharo 3.0 because there were conflicts with a stream library. Anyway it didn't provide a lot of performance (just removed 1 indirection).
2014/1/6 Frank Shearar <frank.shearar@gmail.com>
On 6 January 2014 11:11, Nicolai Hess <nicolaihess@web.de> wrote:
2014/1/6 Clément Bera <bera.clement@gmail.com>
Hello,
here I have a class
A>>== ^ true
Now: a := A new. b := A new. a == b "Answers false" a perform: #== with: b "Answers true"
Do I have to remove the usage of the byte code for #== in the compiler
to
be able to override == ?
No, a==b should be used for "are the same Objects" (pointing to the same object) and not "are equal". Look for example at the commentn for ProtoObject>>==
Given the kinds of things Clément does, I suspect he knows full well the difference between #== and #=.
My understanding is that the compiler inlines #== sends like it does with #timesRepeat: and ifTrue:ifFalse:. So yes, you'd need to fiddle with the compiler for any #== overrides to actually run.
(I'm keen for Marcus to show us how exactly to do that in Opal!)
frank
Nicolai
-- best, Eliot
On 07 Jan 2014, at 03:10, Eliot Miranda <eliot.miranda@gmail.com> wrote:
I don't like all these messages with no lookup. I don't even know if this permits to earn performance now that we have inline caches.
Well, the arithmetic selectors *really* pay their way. Try your experiment with #+ through #~= and I bet you'll see slower loops. I think there's a compromise, which is to only inline the arithmetic selectors. That's what we did with the VisualWorks VM, HPS. There one can set a hidden flag in the image which directs the JIT (HPS only has a JIT) not to inline #== (VW does not inline #class), and change the flag with a primitive. We could (and I think should) do the same. Note that currently only #== and #class are inlined for all objects. The arithmetic selectors #+ et al and #< et al are only inlined by the JIT for SmallInteger, and executed without lookup in the interpreter for SmallInteger x Float.
We removed the #class inclining in Pharo in 2.0 (so already when the old compiler is used). Marcus
On 6 January 2014 10:56, Clément Bera <bera.clement@gmail.com> wrote:
Hello,
here I have a class
A>>== ^ true
Now: a := A new. b := A new. a == b "Answers false" a perform: #== with: b "Answers true"
Do I have to remove the usage of the byte code for #== in the compiler to be able to override == ?
may i ask why you need to override it?
-- Best regards, Igor Stasenko.
You may need to do this if you are using proxies. Alexandre On Jan 6, 2014, at 8:52 AM, Igor Stasenko <siguctua@gmail.com> wrote:
On 6 January 2014 10:56, Clément Bera <bera.clement@gmail.com> wrote: Hello,
here I have a class
A>>== ^ true
Now: a := A new. b := A new. a == b "Answers false" a perform: #== with: b "Answers true"
Do I have to remove the usage of the byte code for #== in the compiler to be able to override == ?
may i ask why you need to override it?
-- Best regards, Igor Stasenko.
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
On 6 janv. 2014, at 13:30, Alexandre Bergel <alexandre.bergel@me.com> wrote:
You may need to do this if you are using proxies.
The fact that #== is not sent is actually really useful for proxies. Because if #== were intercepted by the proxy and forwarded to the target then there is no straightforward way to make the distinction between two proxies on the same object. And if messing with identity breaks all weak maps used for caching proxies.
Alexandre
On Jan 6, 2014, at 8:52 AM, Igor Stasenko <siguctua@gmail.com> wrote:
On 6 January 2014 10:56, Clément Bera <bera.clement@gmail.com> wrote: Hello,
here I have a class
A>>== ^ true
Now: a := A new. b := A new. a == b "Answers false" a perform: #== with: b "Answers true"
Do I have to remove the usage of the byte code for #== in the compiler to be able to override == ?
may i ask why you need to override it?
-- Best regards, Igor Stasenko.
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
On 6 January 2014 14:21, Camille Teruel <camille.teruel@gmail.com> wrote:
On 6 janv. 2014, at 13:30, Alexandre Bergel <alexandre.bergel@me.com> wrote:
You may need to do this if you are using proxies.
The fact that #== is not sent is actually really useful for proxies. Because if #== were intercepted by the proxy and forwarded to the target then there is no straightforward way to make the distinction between two proxies on the same object. And if messing with identity breaks all weak maps used for caching proxies.
right.. proxies are for obvious reasons quite closely related to identity
problematics, and in this regard, changing the #== gives more troubles than it solves, because if you want to have a way to distinguish between proxy and non-proxy, identity is a way to do it, but if there's no way to do identity comparison, then you broke :)
Alexandre
On Jan 6, 2014, at 8:52 AM, Igor Stasenko <siguctua@gmail.com> wrote:
On 6 January 2014 10:56, Clément Bera <bera.clement@gmail.com> wrote: Hello,
here I have a class
A>>== ^ true
Now: a := A new. b := A new. a == b "Answers false" a perform: #== with: b "Answers true"
Do I have to remove the usage of the byte code for #== in the compiler
to be able to override == ?
may i ask why you need to override it?
-- Best regards, Igor Stasenko.
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
-- Best regards, Igor Stasenko.
On 6 janv. 2014, at 10:56, Clément Bera <bera.clement@gmail.com> wrote:
Hello,
here I have a class
A>>== ^ true
Now: a := A new. b := A new. a == b "Answers false" a perform: #== with: b "Answers true"
Do I have to remove the usage of the byte code for #== in the compiler to be able to override == ?
Yes you have to because there is no message sent, just pointer comparison.
participants (8)
-
Alexandre Bergel -
Camille Teruel -
Clément Bera -
Eliot Miranda -
Frank Shearar -
Igor Stasenko -
Marcus Denker -
Nicolai Hess