[Ironruby-core] ConvertTo vs Cast

Peter Bacon Darwin bacondarwin at googlemail.com
Tue Feb 5 13:42:32 EST 2008


OK, so I think that this is a problem with the AST to code generation,
though I really don't understand it deeply enough to say exactly where.

 

If you dump the ASTs from the ruby code the body of the loop looks like
this:

 

{

    (.bound i) = (Object)0;

    .return .comma {

        .try {

            {

                (.bound #rfc).InLoop = (Boolean)True;

                {

                    (.bound #skip-condition) = (Boolean)False;

                    .for (; ; ) {

                        .try {

                            {

                                .if ((.bound #skip-condition) )
{(Void)(.bound #skip-condition) = (Boolean)False;

                                } .else {.if (.action (Boolean) ConvertTo
System.Boolean( // ConvertTo to System.Boolean

                                    .action (Object) InvokeMember <( //
InvokeMember <(Instance, Simple) ReturnNonCallable, IsCallWithThis

                                        (.bound i)

                                        1000

                                    )

                                ) ) {/*empty*/;

                                } .else {.break;

                                }}

                                {

                                    (.bound i) = (Object).action (Object)
InvokeMember +( // InvokeMember +(Instance, Simple) ReturnNonCallable,
IsCallWithThis

                                        (.bound i)

                                        1

                                    );

                                }

                            }

                        } .catch ( BlockUnwinder #unwinder) {

                            (.bound #skip-condition) = (.bound
#unwinder).IsRedo;

                        } .catch ( EvalUnwinder #unwinder) {

                            .if (((.bound #unwinder).Reason ==
(BlockReturnReason)Break) ) {{

                                (.bound #loop-result) = (.bound
#unwinder).ReturnValue;

                                .break;

                            }

                            } .else {

                            .throw ()

                            }}

                    }

                }

            }

        } .finally {

            (.bound #rfc).InLoop = (Boolean)False;

        }

        (.bound #loop-result)

    }

    ;

}

 

No mention of ConvertToInt32 there although it is noticeable that the
(.bound i) value is an object and not a Fixnum.

 

If you dump the generated code you get the following two methods for
invoking the Fixnum methods:

 

public static object $Ruby.Builtins.FixnumOps.LessThan(object[] objArray1,
DynamicSite<object, int, object> site1, CodeContext context1, object obj1,
int num1)

{

    if (((obj1 != null) && (obj1.GetType() == typeof(int))) && (((RubyClass)
objArray1[0]).get_Version() == 0x3b3e))

    {

        bool flag;

        bool flag1 = flag =
FixnumOps.LessThan(Converter.ConvertToInt32(obj1), num1);

        return RuntimeHelpers.BooleanToObject(flag);

    }

    return site1.UpdateBindingAndInvoke(context1, obj1, num1);

}

 

public static object $Ruby.Builtins.FixnumOps.Add(object[] objArray1,
DynamicSite<object, int, object> site1, CodeContext context1, object obj1,
int num1)

{

    if (((obj1 != null) && (obj1.GetType() == typeof(int))) && (((RubyClass)
objArray1[0]).get_Version() == 0x3b3e))

    {

        return FixnumOps.Add((int) obj1, num1);

    }

    return site1.UpdateBindingAndInvoke(context1, obj1, num1);

}

 

Here as Wayne points out the code generator has added in the ConvertToInt32
in the LessThan invocation, whereas in the Add invocation it has used a
direct cast.  Somewhere in the innards of Ruby.dll this decision is being
made and I haven't tracked down where.

 

Clearly it is not necessary to use the conversion method: for a start there
is a clause around the call to the method that tests whether obj1 (self) is
an int.

 

As it happens I am generally doubtful about the inclusion of automated
Conversion in IronRuby at all, apart from perhaps for .NET classes that
don't map directly to Ruby ones, such as byte and float.  The design of the
Ruby builtin classes manages the conversions directly, using such things as
to_s, to_str, to_f, to_int and to_i.  Getting the DLR to do hidden
conversions seems to be overkill and can upset the semantics of the library
classes.

 

Pete

 

 

 

 

 

 

Without looking at the code I can't comment on the main thrust of the mail,
but shouldn't the local variable i be a Fixnum from the word go and
therefore call the LessThan(int, int) method anyway?

 

Yes, LessThan(int, int) is called each time, but an unnecessary call is also
made to method ConvertToInt32 every time around the loop to convert what is
already an integer into an integer.

 

Cheers, Wayne.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://rubyforge.org/pipermail/ironruby-core/attachments/20080205/76a2a3b6/attachment-0001.html 


More information about the Ironruby-core mailing list