[Mono-list] Re: bug report for new JIT

dietmar dietmar@ximian.com
09 Apr 2003 11:44:00 +0200

On Tue, 2003-03-25 at 19:23, Zoltan.2.Varga@nokia.com wrote: 
>                                         Hi,
>  I would like to report two new problems I found.
> - When running with --optimize=shared, case statements for strings
> sometimes do not work 
> because the code generated by the C# compiler calls IsInterned on the
> string and the string
> is not in the interned table because mono_ldstr() is not called yet.
> The old JIT had the
> same problem but it did not manifest itself because it called
> mono_ldstr() during 
> compilation all the time. But this only put the string into the intern
> table for the 
> current appdomain, which is not enough. 
> Here is a testcase:
> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
> using System;
> class Bug {
>         static public void Main() {
>                 string s2 = "C";
>                 string s = "AB" + s2;
>                 switch (s) {
>                 case "ABC":
>                         Console.WriteLine ("OK.");
>                         break;
>                 default:
>                         Console.WriteLine ("NOT OK");
>                         break;
>                 }
>         }
> }

mcs creates the following code for the switch (s)

        IL_001a: ldloc.2
        IL_001b: call string valuetype [corlib]System.String::IsInterned(string)
        IL_0020: stloc.2
        IL_0021: ldloc.2
        IL_0022: ldstr "ABC"
        IL_0027: bne.un IL_0040

The problem is that "ABC" is not interned when IsInterned is called.

csc produces the following code instead:

/* generate a ldstr for each case label*/ 
        IL_0012: ldstr "ABC"
	/* pop all values from evaluation stack */
        IL_0017: leave.s IL_0019
        IL_001e: ldloc.2
        IL_001f: call string valuetype [corlib]System.String::IsInterned(string)
        IL_0024: stloc.2
        IL_0025: ldloc.2
        IL_0026: ldstr "ABC"
        IL_002b: beq.s IL_002f

This code makes sure that all case values are interned before IsInterned
is called. This code also works with AppDomains.

The AOT compiler also triggers this problem.

Paolo said the the correct fix would be to have some runtime magic to
intern all used strings before a method is called. I agree that this
would work, but its complex to implement and produces slow code.

My suggestion is to modify mcs to produce the same code as csc, which
should be easy to implement.

Maybe we should also ask the ECMA people if the really want that
"hidden" runtime feature. IMO its not necessary to make the runtime more
complex than it already is.

- Dietmar