# HG changeset patch # User Jaroslav Tulach # Date 1399358214 -7200 # Node ID 10d26626c42697934c2d476a4a5c7d85bf9ca83d # Parent ce3b83777055d7cbd3bd3682785af6986bbc1bce 1st step in eliminating Class.forName when working with array types. Class.getComponentType on directly allocated arrays does not need that. diff -r ce3b83777055 -r 10d26626c426 rt/emul/mini/src/main/java/java/lang/Class.java --- a/rt/emul/mini/src/main/java/java/lang/Class.java Mon May 05 14:19:25 2014 +0200 +++ b/rt/emul/mini/src/main/java/java/lang/Class.java Tue May 06 08:36:54 2014 +0200 @@ -151,7 +151,7 @@ public static Class forName(String className) throws ClassNotFoundException { if (className.startsWith("[")) { - Class arrType = defineArray(className); + Class arrType = defineArray(className, null); Class c = arrType; while (c != null && c.isArray()) { c = c.getComponentType0(); // verify component type is sane @@ -1544,13 +1544,24 @@ public Class getComponentType() { if (isArray()) { try { - return getComponentType0(); + Class c = getComponentTypeByFnc(); + return c != null ? c : getComponentType0(); } catch (ClassNotFoundException cnfe) { throw new IllegalStateException(cnfe); } } return null; } + + @JavaScriptBody(args = { }, body = + "if (this.fnc) {\n" + + " var c = this.fnc(false).constructor.$class;\n" +// + " java.lang.System.out.println('will call: ' + (!!this.fnc) + ' res: ' + c.jvmName);\n" + + " if (c) return c;\n" + + "}\n" + + "return null;" + ) + private native Class getComponentTypeByFnc(); private Class getComponentType0() throws ClassNotFoundException { String n = getName().substring(1); @@ -1577,24 +1588,26 @@ case 'C': return Character.TYPE; case '[': - return defineArray(n); + return defineArray(n, null); default: throw new ClassNotFoundException("Unknown component type of " + getName()); } } - @JavaScriptBody(args = { "sig" }, body = + @JavaScriptBody(args = { "sig", "fnc" }, body = "if (!sig) sig = '[Ljava/lang/Object;';\n" + "var c = Array[sig];\n" + - "if (c) return c;\n" + - "c = vm.java_lang_Class(true);\n" + - "c.jvmName = sig;\n" + - "c.superclass = vm.java_lang_Object(false).$class;\n" + - "c.array = true;\n" + - "Array[sig] = c;\n" + + "if (!c) {\n" + + " c = vm.java_lang_Class(true);\n" + + " c.jvmName = sig;\n" + + " c.superclass = vm.java_lang_Object(false).$class;\n" + + " c.array = true;\n" + + " Array[sig] = c;\n" + + "}\n" + + "if (!c.fnc) c.fnc = fnc;\n" + "return c;" ) - private static native Class defineArray(String sig); + private static native Class defineArray(String sig, Object fnc); /** * Returns true if and only if this class was declared as an enum in the diff -r ce3b83777055 -r 10d26626c426 rt/emul/mini/src/main/java/java/lang/reflect/Array.java --- a/rt/emul/mini/src/main/java/java/lang/reflect/Array.java Mon May 05 14:19:25 2014 +0200 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Array.java Tue May 06 08:36:54 2014 +0200 @@ -76,7 +76,7 @@ throw new NegativeArraySizeException(); } String sig = findSignature(componentType); - return newArray(componentType.isPrimitive(), sig, length); + return newArray(componentType.isPrimitive(), sig, null, length); } private static String findSignature(Class type) { @@ -630,24 +630,29 @@ * Private */ - @JavaScriptBody(args = { "primitive", "sig", "length" }, body = + @JavaScriptBody(args = { "primitive", "sig", "fn", "length" }, body = "var arr = new Array(length);\n" + "var value = primitive ? 0 : null;\n" + "for(var i = 0; i < length; i++) arr[i] = value;\n" + "arr.jvmName = sig;\n" + + "arr.fnc = fn;\n" +// + "java.lang.System.out.println('Assigned ' + arr.jvmName + ' fn: ' + (!!arr.fnc));\n" + "return arr;" ) + private static native Object newArray0(boolean primitive, String sig, Object fn, int length); @Exported - private static native Object newArray(boolean primitive, String sig, int length); + private static Object newArray(boolean primitive, String sig, Object fn, int length) { + return newArray0(primitive, sig, fn, length); + } @Exported private static Object multiNewArray(String sig, int[] dims, int index) throws IllegalArgumentException, NegativeArraySizeException { if (dims.length == index + 1) { - return newArray(sig.length() == 2, sig, dims[index]); + return newArray(sig.length() == 2, sig, null, dims[index]); } - Object arr = newArray(false, sig, dims[index]); + Object arr = newArray(false, sig, null, dims[index]); String compsig = sig.substring(1); int len = getLength(arr); for (int i = 0; i < len; i++) { diff -r ce3b83777055 -r 10d26626c426 rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_String.js --- a/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_String.js Mon May 05 14:19:25 2014 +0200 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_String.js Tue May 06 08:36:54 2014 +0200 @@ -14,7 +14,7 @@ return arr[indx]; }; Array.prototype.getClass__Ljava_lang_Class_2 = function() { - return vm.java_lang_Class(false).defineArray__Ljava_lang_Class_2Ljava_lang_String_2(this.jvmName); + return vm.java_lang_Class(false).defineArray__Ljava_lang_Class_2Ljava_lang_String_2Ljava_lang_Object_2(this.jvmName, this.fnc); }; Array.prototype.clone__Ljava_lang_Object_2 = function() { var s = this.length; @@ -23,5 +23,6 @@ ret[i] = this[i]; } ret.jvmName = this.jvmName; + ret.fnc = this.fnc; return ret; }; diff -r ce3b83777055 -r 10d26626c426 rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon May 05 14:19:25 2014 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue May 06 08:36:54 2014 +0200 @@ -2117,20 +2117,22 @@ default: throw new IllegalStateException("Array type: " + atype); } emit(smapper, this, - "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](true, '@3', @1);", + "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2Ljava_lang_Object_2I'](true, '@3', null, @1);", smapper.popI(), smapper.pushA(), jvmType); } private void generateANewArray(int type, final StackMapper smapper) throws IOException { String typeName = jc.getClassName(type); + String ref = "null"; if (typeName.startsWith("[")) { - typeName = "[" + typeName; + typeName = "'[" + typeName + "'"; } else { - typeName = "[L" + typeName + ";"; + ref = "vm." + mangleClassName(typeName); + typeName = "'[L" + typeName + ";'"; } emit(smapper, this, - "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](false, '@3', @1);", - smapper.popI(), smapper.pushA(), typeName); + "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2Ljava_lang_Object_2I'](false, @3, @4, @1);", + smapper.popI(), smapper.pushA(), typeName, ref); } private int generateMultiANewArray(int type, final byte[] byteCodes, int i, final StackMapper smapper) throws IOException { diff -r ce3b83777055 -r 10d26626c426 rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Mon May 05 14:19:25 2014 +0200 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Tue May 06 08:36:54 2014 +0200 @@ -17,6 +17,8 @@ */ package org.apidesign.vm4brwsr; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * * @author Jaroslav Tulach @@ -133,6 +135,21 @@ return arr[0]; } + @JavaScriptBody(args = { }, body = + "if (!vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2) throw 'forName not defined';\n" + + "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2 = function(s) {\n" + + " throw 'Do not call me: ' + s;\n" + + "};\n") + private static void disableClassForName() { + } + + public static String nameOfClonedComponent() { + disableClassForName(); + Object[] intArr = new Integer[10]; + intArr = intArr.clone(); + return intArr.getClass().getComponentType().getName(); + } + public static int multiLen() { return new int[1][0].length; } diff -r ce3b83777055 -r 10d26626c426 rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Mon May 05 14:19:25 2014 +0200 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Tue May 06 08:36:54 2014 +0200 @@ -43,6 +43,13 @@ Double.valueOf(15), true ); } + + @Test public void cloneOnArrayAndComponentType() throws Exception { + String exp = Array.nameOfClonedComponent(); + assertExec("getComponentType on clone", Array.class, "nameOfClonedComponent__Ljava_lang_String_2", + exp + ); + } @Test public void realOperationOnArrays() throws Exception { assertEquals(Array.sum(), 105.0, "Computes to 105");