Hi,

2009/8/27 Rick DeNatale <rick.denatale / gmail.com>:
> On Wed, Aug 26, 2009 at 7:25 PM, Yukihiro Matsumoto<matz / ruby-lang.org> wrote:
>> Hi,
>>
>> In message "Re: [ruby-core:25143] Is this an intentional change in 1.9?"
>>    on Thu, 27 Aug 2009 02:30:51 +0900, Rick DeNatale <rick.denatale / gmail.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.  We 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 ||= value


I agree.  I expected that `a.x ||= value' is equal to `a.x || a.x = value',
but 1.9 cheated on me.


  a = Object.new
  def a.foo; nil; end
  def a.foo=(x); :boo; end

  p(a.foo ||= :foo)        #=> :boo
  p(a.foo || a.foo = :foo) #=> :foo


Here is a patch.  When a.x returns nil or false, three more instructions
are executed than current implementation.  I have not measured actual
impact of speed.


Index: compile.c
===================================================================
--- compile.c	(revision 24684)
+++ compile.c	(working copy)
@@ -3842,22 +3842,26 @@
 	  if lcfin  # r o
 	  pop       # r
 	  eval v    # r v
-	  send a=   # v
-	  jump lfin # v
+	  swap      # v r
+	  topn 1    # v r v
+	  send a=   # v ?
+	  jump lfin # v ?

 	  lcfin:      # r o
 	  swap      # o r
+
+	  lfin:       # o ?
 	  pop       # o

-	  lfin:       # v
-
 	  # and
 	  dup       # r o o
 	  unless lcfin
 	  pop       # r
 	  eval v    # r v
-	  send a=   # v
-	  jump lfin # v
+	  swap      # v r
+	  topn 1    # v r v
+	  send a=   # v ?
+	  jump lfin # v ?

 	  # others
 	  eval v    # r o v
@@ -3881,15 +3885,17 @@
 	    }
 	    ADD_INSN(ret, nd_line(node), pop);
 	    COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value);
+	    ADD_INSN(ret, nd_line(node), swap);
+	    ADD_INSN1(ret, nd_line(node), topn, INT2FIX(1));
 	    ADD_SEND(ret, nd_line(node), ID2SYM(node->nd_next->nd_aid),
 		     INT2FIX(1));
 	    ADD_INSNL(ret, nd_line(node), jump, lfin);

 	    ADD_LABEL(ret, lcfin);
 	    ADD_INSN(ret, nd_line(node), swap);
-	    ADD_INSN(ret, nd_line(node), pop);

 	    ADD_LABEL(ret, lfin);
+	    ADD_INSN(ret, nd_line(node), pop);
 	}
 	else {
 	    COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value);

-- 
Yusuke ENDOH <mame / tsg.ne.jp>