1st step in eliminating Class.forName when working with array types. Class.getComponentType on directly allocated arrays does not need that.
1.1 --- a/rt/emul/mini/src/main/java/java/lang/Class.java Mon May 05 14:19:25 2014 +0200
1.2 +++ b/rt/emul/mini/src/main/java/java/lang/Class.java Tue May 06 08:36:54 2014 +0200
1.3 @@ -151,7 +151,7 @@
1.4 public static Class<?> forName(String className)
1.5 throws ClassNotFoundException {
1.6 if (className.startsWith("[")) {
1.7 - Class<?> arrType = defineArray(className);
1.8 + Class<?> arrType = defineArray(className, null);
1.9 Class<?> c = arrType;
1.10 while (c != null && c.isArray()) {
1.11 c = c.getComponentType0(); // verify component type is sane
1.12 @@ -1544,13 +1544,24 @@
1.13 public Class<?> getComponentType() {
1.14 if (isArray()) {
1.15 try {
1.16 - return getComponentType0();
1.17 + Class<?> c = getComponentTypeByFnc();
1.18 + return c != null ? c : getComponentType0();
1.19 } catch (ClassNotFoundException cnfe) {
1.20 throw new IllegalStateException(cnfe);
1.21 }
1.22 }
1.23 return null;
1.24 }
1.25 +
1.26 + @JavaScriptBody(args = { }, body =
1.27 + "if (this.fnc) {\n"
1.28 + + " var c = this.fnc(false).constructor.$class;\n"
1.29 +// + " java.lang.System.out.println('will call: ' + (!!this.fnc) + ' res: ' + c.jvmName);\n"
1.30 + + " if (c) return c;\n"
1.31 + + "}\n"
1.32 + + "return null;"
1.33 + )
1.34 + private native Class<?> getComponentTypeByFnc();
1.35
1.36 private Class<?> getComponentType0() throws ClassNotFoundException {
1.37 String n = getName().substring(1);
1.38 @@ -1577,24 +1588,26 @@
1.39 case 'C':
1.40 return Character.TYPE;
1.41 case '[':
1.42 - return defineArray(n);
1.43 + return defineArray(n, null);
1.44 default:
1.45 throw new ClassNotFoundException("Unknown component type of " + getName());
1.46 }
1.47 }
1.48
1.49 - @JavaScriptBody(args = { "sig" }, body =
1.50 + @JavaScriptBody(args = { "sig", "fnc" }, body =
1.51 "if (!sig) sig = '[Ljava/lang/Object;';\n" +
1.52 "var c = Array[sig];\n" +
1.53 - "if (c) return c;\n" +
1.54 - "c = vm.java_lang_Class(true);\n" +
1.55 - "c.jvmName = sig;\n" +
1.56 - "c.superclass = vm.java_lang_Object(false).$class;\n" +
1.57 - "c.array = true;\n" +
1.58 - "Array[sig] = c;\n" +
1.59 + "if (!c) {\n" +
1.60 + " c = vm.java_lang_Class(true);\n" +
1.61 + " c.jvmName = sig;\n" +
1.62 + " c.superclass = vm.java_lang_Object(false).$class;\n" +
1.63 + " c.array = true;\n" +
1.64 + " Array[sig] = c;\n" +
1.65 + "}\n" +
1.66 + "if (!c.fnc) c.fnc = fnc;\n" +
1.67 "return c;"
1.68 )
1.69 - private static native Class<?> defineArray(String sig);
1.70 + private static native Class<?> defineArray(String sig, Object fnc);
1.71
1.72 /**
1.73 * Returns true if and only if this class was declared as an enum in the
2.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Array.java Mon May 05 14:19:25 2014 +0200
2.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Array.java Tue May 06 08:36:54 2014 +0200
2.3 @@ -76,7 +76,7 @@
2.4 throw new NegativeArraySizeException();
2.5 }
2.6 String sig = findSignature(componentType);
2.7 - return newArray(componentType.isPrimitive(), sig, length);
2.8 + return newArray(componentType.isPrimitive(), sig, null, length);
2.9 }
2.10
2.11 private static String findSignature(Class<?> type) {
2.12 @@ -630,24 +630,29 @@
2.13 * Private
2.14 */
2.15
2.16 - @JavaScriptBody(args = { "primitive", "sig", "length" }, body =
2.17 + @JavaScriptBody(args = { "primitive", "sig", "fn", "length" }, body =
2.18 "var arr = new Array(length);\n"
2.19 + "var value = primitive ? 0 : null;\n"
2.20 + "for(var i = 0; i < length; i++) arr[i] = value;\n"
2.21 + "arr.jvmName = sig;\n"
2.22 + + "arr.fnc = fn;\n"
2.23 +// + "java.lang.System.out.println('Assigned ' + arr.jvmName + ' fn: ' + (!!arr.fnc));\n"
2.24 + "return arr;"
2.25 )
2.26 + private static native Object newArray0(boolean primitive, String sig, Object fn, int length);
2.27 @Exported
2.28 - private static native Object newArray(boolean primitive, String sig, int length);
2.29 + private static Object newArray(boolean primitive, String sig, Object fn, int length) {
2.30 + return newArray0(primitive, sig, fn, length);
2.31 + }
2.32
2.33
2.34 @Exported
2.35 private static Object multiNewArray(String sig, int[] dims, int index)
2.36 throws IllegalArgumentException, NegativeArraySizeException {
2.37 if (dims.length == index + 1) {
2.38 - return newArray(sig.length() == 2, sig, dims[index]);
2.39 + return newArray(sig.length() == 2, sig, null, dims[index]);
2.40 }
2.41 - Object arr = newArray(false, sig, dims[index]);
2.42 + Object arr = newArray(false, sig, null, dims[index]);
2.43 String compsig = sig.substring(1);
2.44 int len = getLength(arr);
2.45 for (int i = 0; i < len; i++) {
3.1 --- a/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_String.js Mon May 05 14:19:25 2014 +0200
3.2 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_String.js Tue May 06 08:36:54 2014 +0200
3.3 @@ -14,7 +14,7 @@
3.4 return arr[indx];
3.5 };
3.6 Array.prototype.getClass__Ljava_lang_Class_2 = function() {
3.7 - return vm.java_lang_Class(false).defineArray__Ljava_lang_Class_2Ljava_lang_String_2(this.jvmName);
3.8 + return vm.java_lang_Class(false).defineArray__Ljava_lang_Class_2Ljava_lang_String_2Ljava_lang_Object_2(this.jvmName, this.fnc);
3.9 };
3.10 Array.prototype.clone__Ljava_lang_Object_2 = function() {
3.11 var s = this.length;
3.12 @@ -23,5 +23,6 @@
3.13 ret[i] = this[i];
3.14 }
3.15 ret.jvmName = this.jvmName;
3.16 + ret.fnc = this.fnc;
3.17 return ret;
3.18 };
4.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon May 05 14:19:25 2014 +0200
4.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue May 06 08:36:54 2014 +0200
4.3 @@ -2117,20 +2117,22 @@
4.4 default: throw new IllegalStateException("Array type: " + atype);
4.5 }
4.6 emit(smapper, this,
4.7 - "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](true, '@3', @1);",
4.8 + "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2Ljava_lang_Object_2I'](true, '@3', null, @1);",
4.9 smapper.popI(), smapper.pushA(), jvmType);
4.10 }
4.11
4.12 private void generateANewArray(int type, final StackMapper smapper) throws IOException {
4.13 String typeName = jc.getClassName(type);
4.14 + String ref = "null";
4.15 if (typeName.startsWith("[")) {
4.16 - typeName = "[" + typeName;
4.17 + typeName = "'[" + typeName + "'";
4.18 } else {
4.19 - typeName = "[L" + typeName + ";";
4.20 + ref = "vm." + mangleClassName(typeName);
4.21 + typeName = "'[L" + typeName + ";'";
4.22 }
4.23 emit(smapper, this,
4.24 - "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](false, '@3', @1);",
4.25 - smapper.popI(), smapper.pushA(), typeName);
4.26 + "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2Ljava_lang_Object_2I'](false, @3, @4, @1);",
4.27 + smapper.popI(), smapper.pushA(), typeName, ref);
4.28 }
4.29
4.30 private int generateMultiANewArray(int type, final byte[] byteCodes, int i, final StackMapper smapper) throws IOException {
5.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Mon May 05 14:19:25 2014 +0200
5.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Tue May 06 08:36:54 2014 +0200
5.3 @@ -17,6 +17,8 @@
5.4 */
5.5 package org.apidesign.vm4brwsr;
5.6
5.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
5.8 +
5.9 /**
5.10 *
5.11 * @author Jaroslav Tulach <jtulach@netbeans.org>
5.12 @@ -133,6 +135,21 @@
5.13 return arr[0];
5.14 }
5.15
5.16 + @JavaScriptBody(args = { }, body =
5.17 + "if (!vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2) throw 'forName not defined';\n"
5.18 + + "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2 = function(s) {\n"
5.19 + + " throw 'Do not call me: ' + s;\n"
5.20 + + "};\n")
5.21 + private static void disableClassForName() {
5.22 + }
5.23 +
5.24 + public static String nameOfClonedComponent() {
5.25 + disableClassForName();
5.26 + Object[] intArr = new Integer[10];
5.27 + intArr = intArr.clone();
5.28 + return intArr.getClass().getComponentType().getName();
5.29 + }
5.30 +
5.31 public static int multiLen() {
5.32 return new int[1][0].length;
5.33 }
6.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Mon May 05 14:19:25 2014 +0200
6.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Tue May 06 08:36:54 2014 +0200
6.3 @@ -43,6 +43,13 @@
6.4 Double.valueOf(15), true
6.5 );
6.6 }
6.7 +
6.8 + @Test public void cloneOnArrayAndComponentType() throws Exception {
6.9 + String exp = Array.nameOfClonedComponent();
6.10 + assertExec("getComponentType on clone", Array.class, "nameOfClonedComponent__Ljava_lang_String_2",
6.11 + exp
6.12 + );
6.13 + }
6.14
6.15 @Test public void realOperationOnArrays() throws Exception {
6.16 assertEquals(Array.sum(), 105.0, "Computes to 105");