Splitting out several complicated (with loops) code generators into separate methods
1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Mar 12 13:01:34 2013 +0100
1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Mar 12 15:14:20 2013 +0100
1.3 @@ -898,40 +898,11 @@
1.4 break;
1.5 }
1.6 case opc_lookupswitch: {
1.7 - int table = i / 4 * 4 + 4;
1.8 - int dflt = i + readInt4(byteCodes, table);
1.9 - table += 4;
1.10 - int n = readInt4(byteCodes, table);
1.11 - table += 4;
1.12 - out.append("switch (").append(smapper.popI()).append(") {\n");
1.13 - while (n-- > 0) {
1.14 - int cnstnt = readInt4(byteCodes, table);
1.15 - table += 4;
1.16 - int offset = i + readInt4(byteCodes, table);
1.17 - table += 4;
1.18 - out.append(" case " + cnstnt).append(": "); goTo(out, i, offset); out.append('\n');
1.19 - }
1.20 - out.append(" default: "); goTo(out, i, dflt); out.append("\n}");
1.21 - i = table - 1;
1.22 + i = generateLookupSwitch(i, byteCodes, smapper);
1.23 break;
1.24 }
1.25 case opc_tableswitch: {
1.26 - int table = i / 4 * 4 + 4;
1.27 - int dflt = i + readInt4(byteCodes, table);
1.28 - table += 4;
1.29 - int low = readInt4(byteCodes, table);
1.30 - table += 4;
1.31 - int high = readInt4(byteCodes, table);
1.32 - table += 4;
1.33 - out.append("switch (").append(smapper.popI()).append(") {\n");
1.34 - while (low <= high) {
1.35 - int offset = i + readInt4(byteCodes, table);
1.36 - table += 4;
1.37 - out.append(" case " + low).append(":"); goTo(out, i, offset); out.append('\n');
1.38 - low++;
1.39 - }
1.40 - out.append(" default: "); goTo(out, i, dflt); out.append("\n}");
1.41 - i = table - 1;
1.42 + i = generateTableSwitch(i, byteCodes, smapper);
1.43 break;
1.44 }
1.45 case opc_invokeinterface: {
1.46 @@ -958,50 +929,18 @@
1.47 }
1.48 case opc_newarray:
1.49 int atype = readUByte(byteCodes, ++i);
1.50 - String jvmType;
1.51 - switch (atype) {
1.52 - case 4: jvmType = "[Z"; break;
1.53 - case 5: jvmType = "[C"; break;
1.54 - case 6: jvmType = "[F"; break;
1.55 - case 7: jvmType = "[D"; break;
1.56 - case 8: jvmType = "[B"; break;
1.57 - case 9: jvmType = "[S"; break;
1.58 - case 10: jvmType = "[I"; break;
1.59 - case 11: jvmType = "[J"; break;
1.60 - default: throw new IllegalStateException("Array type: " + atype);
1.61 - }
1.62 - emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
1.63 - smapper.popI(), smapper.pushA(), jvmType);
1.64 + generateNewArray(atype, smapper);
1.65 break;
1.66 case opc_anewarray: {
1.67 int type = readIntArg(byteCodes, i);
1.68 i += 2;
1.69 - String typeName = jc.getClassName(type);
1.70 - if (typeName.startsWith("[")) {
1.71 - typeName = "[" + typeName;
1.72 - } else {
1.73 - typeName = "[L" + typeName + ";";
1.74 - }
1.75 - emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
1.76 - smapper.popI(), smapper.pushA(), typeName);
1.77 + generateANewArray(type, smapper);
1.78 break;
1.79 }
1.80 case opc_multianewarray: {
1.81 int type = readIntArg(byteCodes, i);
1.82 i += 2;
1.83 - String typeName = jc.getClassName(type);
1.84 - int dim = readUByte(byteCodes, ++i);
1.85 - StringBuilder dims = new StringBuilder();
1.86 - dims.append('[');
1.87 - for (int d = 0; d < dim; d++) {
1.88 - if (d != 0) {
1.89 - dims.insert(1, ",");
1.90 - }
1.91 - dims.insert(1, smapper.popI());
1.92 - }
1.93 - dims.append(']');
1.94 - emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
1.95 - dims.toString(), smapper.pushA(), typeName);
1.96 + i = generateMultiANewArray(type, byteCodes, i, smapper);
1.97 break;
1.98 }
1.99 case opc_arraylength:
1.100 @@ -1269,32 +1208,13 @@
1.101 }
1.102 case opc_checkcast: {
1.103 int indx = readIntArg(byteCodes, i);
1.104 - final String type = jc.getClassName(indx);
1.105 - if (!type.startsWith("[")) {
1.106 - emit(out,
1.107 - "if (@1 !== null && !@1.$instOf_@2) throw {};",
1.108 - smapper.getA(0), type.replace('/', '_'));
1.109 - } else {
1.110 - emit(out, "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@2').cast__Ljava_lang_Object_2Ljava_lang_Object_2(@1);",
1.111 - smapper.getA(0), type
1.112 - );
1.113 - }
1.114 + generateCheckcast(indx, smapper);
1.115 i += 2;
1.116 break;
1.117 }
1.118 case opc_instanceof: {
1.119 int indx = readIntArg(byteCodes, i);
1.120 - final String type = jc.getClassName(indx);
1.121 - if (!type.startsWith("[")) {
1.122 - emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
1.123 - smapper.popA(), smapper.pushI(),
1.124 - type.replace('/', '_'));
1.125 - } else {
1.126 - emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);",
1.127 - smapper.popA(), smapper.pushI(),
1.128 - type
1.129 - );
1.130 - }
1.131 + generateInstanceOf(indx, smapper);
1.132 i += 2;
1.133 break;
1.134 }
1.135 @@ -1330,11 +1250,7 @@
1.136 }
1.137 }
1.138 if (debug(" //")) {
1.139 - for (int j = prev; j <= i; j++) {
1.140 - out.append(" ");
1.141 - final int cc = readUByte(byteCodes, j);
1.142 - out.append(Integer.toString(cc));
1.143 - }
1.144 + generateByteCodeComment(prev, i, byteCodes);
1.145 }
1.146 out.append("\n");
1.147 }
1.148 @@ -1879,4 +1795,127 @@
1.149 emit(out, pattern, param);
1.150 goTo(out, current, to);
1.151 }
1.152 +
1.153 + private void generateNewArray(int atype, final StackMapper smapper) throws IOException, IllegalStateException {
1.154 + String jvmType;
1.155 + switch (atype) {
1.156 + case 4: jvmType = "[Z"; break;
1.157 + case 5: jvmType = "[C"; break;
1.158 + case 6: jvmType = "[F"; break;
1.159 + case 7: jvmType = "[D"; break;
1.160 + case 8: jvmType = "[B"; break;
1.161 + case 9: jvmType = "[S"; break;
1.162 + case 10: jvmType = "[I"; break;
1.163 + case 11: jvmType = "[J"; break;
1.164 + default: throw new IllegalStateException("Array type: " + atype);
1.165 + }
1.166 + emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
1.167 + smapper.popI(), smapper.pushA(), jvmType);
1.168 + }
1.169 +
1.170 + private void generateANewArray(int type, final StackMapper smapper) throws IOException {
1.171 + String typeName = jc.getClassName(type);
1.172 + if (typeName.startsWith("[")) {
1.173 + typeName = "[" + typeName;
1.174 + } else {
1.175 + typeName = "[L" + typeName + ";";
1.176 + }
1.177 + emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
1.178 + smapper.popI(), smapper.pushA(), typeName);
1.179 + }
1.180 +
1.181 + private int generateMultiANewArray(int type, final byte[] byteCodes, int i, final StackMapper smapper) throws IOException {
1.182 + String typeName = jc.getClassName(type);
1.183 + int dim = readUByte(byteCodes, ++i);
1.184 + StringBuilder dims = new StringBuilder();
1.185 + dims.append('[');
1.186 + for (int d = 0; d < dim; d++) {
1.187 + if (d != 0) {
1.188 + dims.insert(1, ",");
1.189 + }
1.190 + dims.insert(1, smapper.popI());
1.191 + }
1.192 + dims.append(']');
1.193 + emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
1.194 + dims.toString(), smapper.pushA(), typeName);
1.195 + return i;
1.196 + }
1.197 +
1.198 + private int generateTableSwitch(int i, final byte[] byteCodes, final StackMapper smapper) throws IOException {
1.199 + int table = i / 4 * 4 + 4;
1.200 + int dflt = i + readInt4(byteCodes, table);
1.201 + table += 4;
1.202 + int low = readInt4(byteCodes, table);
1.203 + table += 4;
1.204 + int high = readInt4(byteCodes, table);
1.205 + table += 4;
1.206 + out.append("switch (").append(smapper.popI()).append(") {\n");
1.207 + while (low <= high) {
1.208 + int offset = i + readInt4(byteCodes, table);
1.209 + table += 4;
1.210 + out.append(" case " + low).append(":"); goTo(out, i, offset); out.append('\n');
1.211 + low++;
1.212 + }
1.213 + out.append(" default: ");
1.214 + goTo(out, i, dflt);
1.215 + out.append("\n}");
1.216 + i = table - 1;
1.217 + return i;
1.218 + }
1.219 +
1.220 + private int generateLookupSwitch(int i, final byte[] byteCodes, final StackMapper smapper) throws IOException {
1.221 + int table = i / 4 * 4 + 4;
1.222 + int dflt = i + readInt4(byteCodes, table);
1.223 + table += 4;
1.224 + int n = readInt4(byteCodes, table);
1.225 + table += 4;
1.226 + out.append("switch (").append(smapper.popI()).append(") {\n");
1.227 + while (n-- > 0) {
1.228 + int cnstnt = readInt4(byteCodes, table);
1.229 + table += 4;
1.230 + int offset = i + readInt4(byteCodes, table);
1.231 + table += 4;
1.232 + out.append(" case " + cnstnt).append(": "); goTo(out, i, offset); out.append('\n');
1.233 + }
1.234 + out.append(" default: ");
1.235 + goTo(out, i, dflt);
1.236 + out.append("\n}");
1.237 + i = table - 1;
1.238 + return i;
1.239 + }
1.240 +
1.241 + private void generateInstanceOf(int indx, final StackMapper smapper) throws IOException {
1.242 + final String type = jc.getClassName(indx);
1.243 + if (!type.startsWith("[")) {
1.244 + emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
1.245 + smapper.popA(), smapper.pushI(),
1.246 + type.replace('/', '_'));
1.247 + } else {
1.248 + emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);",
1.249 + smapper.popA(), smapper.pushI(),
1.250 + type
1.251 + );
1.252 + }
1.253 + }
1.254 +
1.255 + private void generateCheckcast(int indx, final StackMapper smapper) throws IOException {
1.256 + final String type = jc.getClassName(indx);
1.257 + if (!type.startsWith("[")) {
1.258 + emit(out,
1.259 + "if (@1 !== null && !@1.$instOf_@2) throw {};",
1.260 + smapper.getA(0), type.replace('/', '_'));
1.261 + } else {
1.262 + emit(out, "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@2').cast__Ljava_lang_Object_2Ljava_lang_Object_2(@1);",
1.263 + smapper.getA(0), type
1.264 + );
1.265 + }
1.266 + }
1.267 +
1.268 + private void generateByteCodeComment(int prev, int i, final byte[] byteCodes) throws IOException {
1.269 + for (int j = prev; j <= i; j++) {
1.270 + out.append(" ");
1.271 + final int cc = readUByte(byteCodes, j);
1.272 + out.append(Integer.toString(cc));
1.273 + }
1.274 + }
1.275 }