# Monday, 31 March 2003
Sockets
I completed most of the Socket code and fixed a few bugs. Mauve results (with current Classpath CVS code): 172 of 7707 tests failed.

I updated to BlogX rev 20 and this means that the RSS will now contain xhtml:body (for the new entries). Chris says: "So, if you favorite aggregator isn't showing the full text of my blog, send them a mail and get them to support <xhtml:body>!"

I've updated the source and binaries snapshots
Monday, 31 March 2003 17:06:44 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]
# Wednesday, 19 March 2003
System.arraycopy

At first sight, it might seem that System.arraycopy is not a very interesting method, but once you dig into it, it turns out to be an interesting case study.

.NET has a very similar method Array.Copy and one of its overloads has the exact same signature as its Java cousin, but throws slightly different exceptions and there is a tiny difference in behavior. So an initial naïve implementation of System.arraycopy would look as follows:

public static void arraycopy(object src, int srcStart,
       object dest, int destStart, int length) {
    try {
        Array.Copy(src, srcStart, dest, destStart, length);
    } catch(ArgumentNullException) {
        throw new NullReferenceException();
    } catch(ArgumentException) {
        throw new ArrayIndexOutOfBoundsException();
    } catch(ArrayTypeMismatchException) {
        throw new ArrayStoreException();
    } catch(InvalidCastException) {
        throw new ArrayStoreException();
    }
}

This works fairly well, but it has two problems. The first problem is that it is too powerful. Array.Copy allows widening conversions for primitive types. This means, for example, that it is possible to copy a byte array to an int array. Java doesn’t allow this. The second problem is more subtle, Javadocs for System.arraycopy say:

“Otherwise, if any actual component of the source array from position srcPos through srcPos1 cannot be converted to the component type of the destination array by assignment conversion, an ArrayStoreException is thrown. In this case, let k be the smallest nonnegative integer less than length such that src[srcPosk] cannot be converted to the component type of the destination array; when the exception is thrown, source array components from positions srcPos through srcPosk-1 will already have been copied to destination array positions destPos through destPosk-1 and no other positions of the destination array will have been modified.”

In other words, if an ArrayStoreException is thrown, all elements prior to the one that failed are copied. In contrast to this, the .NET documentation for Array.Copy says:

“If this method throws an exception while copying, the state of destinationArray is undefined.”

So to be strictly correct, we cannot rely on Array.Copy to implement copying of reference arrays that might throw an exception during copying. Here is a better implementation of System.arraycopy:

public static void arraycopy(object src, int srcStart,
       object dest, int destStart, int length) {
    // fast path if source and destination are same
    if(src != dest) {
        Type type_src = src.GetType();
        Type type_dst = dest.GetType();
        // fast path if arrays are of identical type
        
if(type_src != type_dst) {
            if(len < 0) {
                throw newArrayIndexOutOfBoundsException();
            }
            try {
                Object[] src1 = (Object[])src;
                Object[] dst1 = (Object[])dest;
                for(; len > 0; len--) {
                    dst1[destStart++] = src1[srcStart++];
                }
            } catch(InvalidCastException) {
                throw JavaException.ArrayStoreException();
            }
        }
    }
    try {
        Array.Copy((Array)src, srcStart,
                   (Array)dest, destStart, length);
    } catch(ArgumentNullException) {
        throw new NullReferenceException();
    } catch(ArgumentException) {
        throw new ArrayIndexOutOfBoundsException();
    } catch(InvalidCastException) {
        throw new ArrayStoreException();
    }
}

I think this is a correct implementation of System.arraycopy. It’s still not perfect though, because it turns out to be really slow. Here is a small benchmark:

class arraycopy {
    public static void main(String[] args){
        test(10, 10000000);
        test(100, 1000000);
        test(1000, 100000);
    }

    private static void test(int size, int count) {
        int[] a = new int[size];
        int[] b = new int[size];
        long start = System.currentTimeMillis();
        for(int i = 0; i < count; i++) {
            System.arraycopy(a, 0, b, 0, a.length);
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

Here are the results for the JDK 1.1 Symantec JIT, JRE 1.4.1 HotSpot Client VM and IKVM running on .NET 1.0:

Symantec

JRE 1.4.1

IKVM

10

1012

2343

12127

100

340

531

1402

1000

120

310

340

It’s obvious that for small arrays, the overhead is really large. The reason this is so much slower than the Java version is probably because of the cost of the call to GetType combined with the extra checking going on inside Array.Copy. If Sun had only provided overloaded versions of System.arraycopy for each type of primitive array, we wouldn’t need to do so much type checking! It turns out that even without these overloads we can still get the same result (in many cases), because the verifier often knows the types of the arguments. In compiles.cs I added some code to the invokestatic handler to check for invocations of System.arraycopy and if the array arguments are known to be primitive arrays, the call gets redirected to a more efficient arraycopy implementation.

Here is where the call to System.arraycopy in the above benchmark gets redirected to:

public static void arraycopy_primitive_4(Array src,
       int srcStart, Array dest, int destStart, int len) {

    try {

        checked {

            Buffer.BlockCopy(src, srcStart << 2,
                       dest, destStart << 2, len << 2);

            return;

        }

    } catch(ArgumentNullException) {

        throw new NullReferenceException();

    } catch(OverflowException) {

        throw new ArrayIndexOutOfBoundsException();

    } catch(ArgumentException) {

        throw new ArrayIndexOutOfBoundsException();

    }

}

No more calls to GetType and no more casts to Array are required. In addition, since we know that the arrays are both of the same primitive type, we can use the more efficient Buffer.BlockCopy instead of Array.Copy.

Here are the performance results for the new implementation:

Symantec

JRE 1.4.1

IKVM

10

1012

2343

1713

100

340

531

381

1000

120

310

230

Obviously a worthwhile improvement. For completeness, here are the performance results for doing the arraycopy with a simple for loop (i.e. in a modified version of the benchmark that doesn't call System.arraycopy , but instead has simple simple method that copies the array using a for loop):

for(; len > 0; len--)
    src[srcStart++] = dest[destStart++];

Symantec

JRE 1.4.1

IKVM

10

1853

2724

1522

100

1542

2444

1162

1000

1532

2363

1131

Wednesday, 19 March 2003 18:00:14 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Monday, 17 March 2003
Cobol

On the ikvm-developers list, Brian Sullivan reported that he had partial success with running a Cobol application (compiled with PERCobol to a Java jar) under ikvm.

The exception was caused by some missing org.xml.sax.* classes.

In unrelated news, I checked in several changes and made new source and binaries snapshots.

Monday, 17 March 2003 15:20:43 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Thursday, 13 March 2003
Welcome on the other side

Like many before me, I finally grew tired of Radio and so I've migrated to BlogX by Chris Anderson. All I need now is an rss aggregator, preferably ASP.NET based.

Thursday, 13 March 2003 14:28:06 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Monday, 03 March 2003
Hello Mono (2)
C:\>mono --noinline --share-code c:\ikvm\bin\ikvm.exe hello
** Warning **: cannot find C:\cygwin\home\lalo\go-mono\install\
etc\mono\machine.config
Trying to load app config file...
Hello World

The latest ikvm binaries together with Mono 0.21 now run Hello World!

Many thanks to everyone at Ximian, the Mono contributors and especially Zoltan Varga!

The --noinline and --share-code options are needed to work around a bug in the current Mono JIT that cause it to call the class constructors to eagerly.

I've updated the source and binaries snapshots.

Monday, 03 March 2003 11:57:22 (W. Europe Standard Time, UTC+01:00)  #    Comments [2]