On Wed, Aug 26, 2009 at 7:25 PM, Yukihiro Matsumoto<matz / ruby-lang.org> wro=
te:
> Hi,
>
> In message "Re: [ruby-core:25143] Is this an intentional change in 1.9?"
> =A0 =A0on Thu, 27 Aug 2009 02:30:51 +0900, Rick DeNatale <rick.denatale@g=
mail.com> writes:
>
> |This seems like a 1.9 bug. Is it?
>
> I vaguely remember ko1 explained me about the change due to a YARV
> internal issue. =A0We have to wait ko1 to determine it's bug or not.

I think it's a code generation issue, and also that it's important not
to change the semantics of a.x ||=3D value

First here's what's being generated for an instruction sequence:

$ ruby1.9 -e'puts VM::InstructionSequence.compile("obj=3DObject.new;a =3D
obj.x ||=3D 2").disassemble'
=3D=3D disasm: <ISeq:<compiled>@<compiled>>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
local table (size: 3, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 3] obj        [ 2] a
0000 getinlinecache   <ic>, 7                                         (   1=
)
0003 getconstant      :Object
0005 setinlinecache   0
0007 send             :new, 0, nil, 0, <ic>
0013 setlocal         obj
0015 getlocal         obj
0017 dup
0018 send             :x, 0, nil, 0, <ic>
0024 dup
0025 branchif         38
0027 pop
0028 putobject        2
0030 send             :x=3D, 1, nil, 0, <ic>
0036 jump             40
0038 swap
0039 pop
0040 dup
0041 setlocal         a
0043 leave

In the case where obj.x returns a truthy value this code is clearly
evaluating to the return value of the setter and not the rhs.

I think that something like this would work  (I made the branch target
symbolic so I wouldn't need to count bytes.

     getinlinecache   <ic>, 7                                         (   1=
)
     getconstant      :Object
     setinlinecache   0
     send             :new, 0, nil, 0, <ic>
     setlocal         obj
     getlocal         obj
     dup
     send             :x, 0, nil, 0, <ic>
     dup
     branchif         skip
     pop
     putobject        2
# inserted instruction
     dupn             2           #duplicate receiver of x=3D and rhs
value stack now has obj 2 obj 2
# end inserted instruction
     send             :x=3D, 1, nil, 0, <ic>
# inserted instructions
     pop                           # discard result of send, stack now has =
obj 2
     swap                         # swap stack how has 2 obj
     pop                           # discard receiver of x=3D stack now
has rhs (2)
# end of inserted instructions
     jump             set
skip swap
set  pop
     dup
     setlocal         a
     leave

I'm assuming here that dup n 2 changes the top of the stack (stack
grows to the right so the rightmost item is the top

value 1 value 2

to

value 1 value 2 value 1 value 2

--=20
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale