Jump instructions need to use signed and constant pool referencing instructions unsigned short. Also getting ready for reading signed short composed from (improperly) two unsigned bytes.
1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Mar 20 14:01:43 2013 +0100
1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Mar 20 21:24:36 2013 +0100
1.3 @@ -782,7 +782,7 @@
1.4 }
1.5 case opc_ldc_w:
1.6 case opc_ldc2_w: {
1.7 - int indx = readIntArg(byteCodes, i);
1.8 + int indx = readUShortArg(byteCodes, i);
1.9 i += 2;
1.10 String v = encodeConstant(indx);
1.11 int type = VarType.fromConstantType(jc.getTag(indx));
1.12 @@ -824,56 +824,56 @@
1.13 "==", topMostLabel);
1.14 break;
1.15 case opc_ifeq: {
1.16 - int indx = i + readIntArg(byteCodes, i);
1.17 + int indx = i + readShortArg(byteCodes, i);
1.18 emitIf(out, "if (@1 == 0) ",
1.19 smapper.popI(), i, indx, topMostLabel);
1.20 i += 2;
1.21 break;
1.22 }
1.23 case opc_ifne: {
1.24 - int indx = i + readIntArg(byteCodes, i);
1.25 + int indx = i + readShortArg(byteCodes, i);
1.26 emitIf(out, "if (@1 != 0) ",
1.27 smapper.popI(), i, indx, topMostLabel);
1.28 i += 2;
1.29 break;
1.30 }
1.31 case opc_iflt: {
1.32 - int indx = i + readIntArg(byteCodes, i);
1.33 + int indx = i + readShortArg(byteCodes, i);
1.34 emitIf(out, "if (@1 < 0) ",
1.35 smapper.popI(), i, indx, topMostLabel);
1.36 i += 2;
1.37 break;
1.38 }
1.39 case opc_ifle: {
1.40 - int indx = i + readIntArg(byteCodes, i);
1.41 + int indx = i + readShortArg(byteCodes, i);
1.42 emitIf(out, "if (@1 <= 0) ",
1.43 smapper.popI(), i, indx, topMostLabel);
1.44 i += 2;
1.45 break;
1.46 }
1.47 case opc_ifgt: {
1.48 - int indx = i + readIntArg(byteCodes, i);
1.49 + int indx = i + readShortArg(byteCodes, i);
1.50 emitIf(out, "if (@1 > 0) ",
1.51 smapper.popI(), i, indx, topMostLabel);
1.52 i += 2;
1.53 break;
1.54 }
1.55 case opc_ifge: {
1.56 - int indx = i + readIntArg(byteCodes, i);
1.57 + int indx = i + readShortArg(byteCodes, i);
1.58 emitIf(out, "if (@1 >= 0) ",
1.59 smapper.popI(), i, indx, topMostLabel);
1.60 i += 2;
1.61 break;
1.62 }
1.63 case opc_ifnonnull: {
1.64 - int indx = i + readIntArg(byteCodes, i);
1.65 + int indx = i + readShortArg(byteCodes, i);
1.66 emitIf(out, "if (@1 !== null) ",
1.67 smapper.popA(), i, indx, topMostLabel);
1.68 i += 2;
1.69 break;
1.70 }
1.71 case opc_ifnull: {
1.72 - int indx = i + readIntArg(byteCodes, i);
1.73 + int indx = i + readShortArg(byteCodes, i);
1.74 emitIf(out, "if (@1 === null) ",
1.75 smapper.popA(), i, indx, topMostLabel);
1.76 i += 2;
1.77 @@ -900,7 +900,7 @@
1.78 ">=", topMostLabel);
1.79 break;
1.80 case opc_goto: {
1.81 - int indx = i + readIntArg(byteCodes, i);
1.82 + int indx = i + readShortArg(byteCodes, i);
1.83 goTo(out, i, indx, topMostLabel);
1.84 i += 2;
1.85 break;
1.86 @@ -927,7 +927,7 @@
1.87 i = invokeStaticMethod(byteCodes, i, smapper, true);
1.88 break;
1.89 case opc_new: {
1.90 - int indx = readIntArg(byteCodes, i);
1.91 + int indx = readUShortArg(byteCodes, i);
1.92 String ci = jc.getClassName(indx);
1.93 emit(out, "var @1 = new @2;",
1.94 smapper.pushA(), accessClass(ci.replace('/', '_')));
1.95 @@ -940,13 +940,13 @@
1.96 generateNewArray(atype, smapper);
1.97 break;
1.98 case opc_anewarray: {
1.99 - int type = readIntArg(byteCodes, i);
1.100 + int type = readUShortArg(byteCodes, i);
1.101 i += 2;
1.102 generateANewArray(type, smapper);
1.103 break;
1.104 }
1.105 case opc_multianewarray: {
1.106 - int type = readIntArg(byteCodes, i);
1.107 + int type = readUShortArg(byteCodes, i);
1.108 i += 2;
1.109 i = generateMultiANewArray(type, byteCodes, i, smapper);
1.110 break;
1.111 @@ -1162,11 +1162,11 @@
1.112 case opc_sipush:
1.113 emit(out, "var @1 = @2;",
1.114 smapper.pushI(),
1.115 - Integer.toString(readIntArg(byteCodes, i)));
1.116 + Integer.toString(readShortArg(byteCodes, i)));
1.117 i += 2;
1.118 break;
1.119 case opc_getfield: {
1.120 - int indx = readIntArg(byteCodes, i);
1.121 + int indx = readUShortArg(byteCodes, i);
1.122 String[] fi = jc.getFieldInfoName(indx);
1.123 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.124 final String mangleClass = mangleSig(fi[0]);
1.125 @@ -1179,7 +1179,7 @@
1.126 break;
1.127 }
1.128 case opc_putfield: {
1.129 - int indx = readIntArg(byteCodes, i);
1.130 + int indx = readUShortArg(byteCodes, i);
1.131 String[] fi = jc.getFieldInfoName(indx);
1.132 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.133 final String mangleClass = mangleSig(fi[0]);
1.134 @@ -1193,7 +1193,7 @@
1.135 break;
1.136 }
1.137 case opc_getstatic: {
1.138 - int indx = readIntArg(byteCodes, i);
1.139 + int indx = readUShortArg(byteCodes, i);
1.140 String[] fi = jc.getFieldInfoName(indx);
1.141 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.142 emit(out, "var @1 = @2(false)._@3();",
1.143 @@ -1204,7 +1204,7 @@
1.144 break;
1.145 }
1.146 case opc_putstatic: {
1.147 - int indx = readIntArg(byteCodes, i);
1.148 + int indx = readUShortArg(byteCodes, i);
1.149 String[] fi = jc.getFieldInfoName(indx);
1.150 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.151 emit(out, "@1(false)._@2(@3);",
1.152 @@ -1215,13 +1215,13 @@
1.153 break;
1.154 }
1.155 case opc_checkcast: {
1.156 - int indx = readIntArg(byteCodes, i);
1.157 + int indx = readUShortArg(byteCodes, i);
1.158 generateCheckcast(indx, smapper);
1.159 i += 2;
1.160 break;
1.161 }
1.162 case opc_instanceof: {
1.163 - int indx = readIntArg(byteCodes, i);
1.164 + int indx = readUShortArg(byteCodes, i);
1.165 generateInstanceOf(indx, smapper);
1.166 i += 2;
1.167 break;
1.168 @@ -1273,7 +1273,7 @@
1.169 }
1.170
1.171 private int generateIf(byte[] byteCodes, int i, final Variable v2, final Variable v1, final String test, int topMostLabel) throws IOException {
1.172 - int indx = i + readIntArg(byteCodes, i);
1.173 + int indx = i + readShortArg(byteCodes, i);
1.174 out.append("if (").append(v1)
1.175 .append(' ').append(test).append(' ')
1.176 .append(v2).append(") ");
1.177 @@ -1281,11 +1281,6 @@
1.178 return i + 2;
1.179 }
1.180
1.181 - private int readIntArg(byte[] byteCodes, int offsetInstruction) {
1.182 - final int indxHi = byteCodes[offsetInstruction + 1] << 8;
1.183 - final int indxLo = byteCodes[offsetInstruction + 2];
1.184 - return (indxHi & 0xffffff00) | (indxLo & 0xff);
1.185 - }
1.186 private int readInt4(byte[] byteCodes, int offset) {
1.187 final int d = byteCodes[offset + 0] << 24;
1.188 final int c = byteCodes[offset + 1] << 16;
1.189 @@ -1293,18 +1288,25 @@
1.190 final int a = byteCodes[offset + 3];
1.191 return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff);
1.192 }
1.193 - private int readUByte(byte[] byteCodes, int offset) {
1.194 + private static int readUByte(byte[] byteCodes, int offset) {
1.195 return byteCodes[offset] & 0xff;
1.196 }
1.197
1.198 - private int readUShort(byte[] byteCodes, int offset) {
1.199 + private static int readUShort(byte[] byteCodes, int offset) {
1.200 return ((byteCodes[offset] & 0xff) << 8)
1.201 | (byteCodes[offset + 1] & 0xff);
1.202 }
1.203 + private static int readUShortArg(byte[] byteCodes, int offsetInstruction) {
1.204 + return readUShort(byteCodes, offsetInstruction + 1);
1.205 + }
1.206
1.207 - private int readShort(byte[] byteCodes, int offset) {
1.208 - return (byteCodes[offset] << 8)
1.209 - | (byteCodes[offset + 1] & 0xff);
1.210 + private static int readShort(byte[] byteCodes, int offset) {
1.211 + int signed = byteCodes[offset];
1.212 + byte b0 = (byte)signed;
1.213 + return (b0 << 8) | (byteCodes[offset + 1] & 0xff);
1.214 + }
1.215 + private static int readShortArg(byte[] byteCodes, int offsetInstruction) {
1.216 + return readShort(byteCodes, offsetInstruction + 1);
1.217 }
1.218
1.219 private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
1.220 @@ -1432,7 +1434,7 @@
1.221
1.222 private int invokeStaticMethod(byte[] byteCodes, int i, final StackMapper mapper, boolean isStatic)
1.223 throws IOException {
1.224 - int methodIndex = readIntArg(byteCodes, i);
1.225 + int methodIndex = readUShortArg(byteCodes, i);
1.226 String[] mi = jc.getFieldInfoName(methodIndex);
1.227 char[] returnType = { 'V' };
1.228 StringBuilder cnt = new StringBuilder();
1.229 @@ -1477,7 +1479,7 @@
1.230 }
1.231 private int invokeVirtualMethod(byte[] byteCodes, int i, final StackMapper mapper)
1.232 throws IOException {
1.233 - int methodIndex = readIntArg(byteCodes, i);
1.234 + int methodIndex = readUShortArg(byteCodes, i);
1.235 String[] mi = jc.getFieldInfoName(methodIndex);
1.236 char[] returnType = { 'V' };
1.237 StringBuilder cnt = new StringBuilder();
2.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java Wed Mar 20 14:01:43 2013 +0100
2.2 +++ b/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java Wed Mar 20 21:24:36 2013 +0100
2.3 @@ -17,6 +17,7 @@
2.4 */
2.5 package org.apidesign.bck2brwsr.tck;
2.6
2.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
2.8 import org.apidesign.bck2brwsr.vmtest.Compare;
2.9 import org.apidesign.bck2brwsr.vmtest.VMTest;
2.10 import org.testng.annotations.Factory;
2.11 @@ -94,6 +95,50 @@
2.12 @Compare public byte divisionReminder() {
2.13 return mod((byte)1, (byte)2);
2.14 }
2.15 +
2.16 + private static int readShort(byte[] byteCodes, int offset) {
2.17 + int signed = byteCodes[offset];
2.18 + byte b0 = (byte)signed;
2.19 + return (b0 << 8) | (byteCodes[offset + 1] & 0xff);
2.20 + }
2.21 +
2.22 + private static int readShortArg(byte[] byteCodes, int offsetInstruction) {
2.23 + return readShort(byteCodes, offsetInstruction + 1);
2.24 + }
2.25 +
2.26 + @Compare public int readIntArgs255and156() {
2.27 + final byte[] arr = new byte[] { (byte)0, (byte)255, (byte)156 };
2.28 +
2.29 + assert arr[1] == -1 : "First byte: " + arr[1];
2.30 + assert arr[2] == -100 : "Second byte: " + arr[2];
2.31 + final int ret = readShortArg(arr, 0);
2.32 + assert ret < 65000: "Value: " + ret;
2.33 + return ret;
2.34 + }
2.35 +
2.36 + @JavaScriptBody(args = { "arr" }, body = "arr[1] = 255; arr[2] = 156; return arr;")
2.37 + private static byte[] fill255and156(byte[] arr) {
2.38 + arr[1] = (byte)255;
2.39 + arr[2] = (byte)156;
2.40 + return arr;
2.41 + }
2.42 +
2.43 + @Compare public int readIntArgs255and156JSArray() {
2.44 + final byte[] arr = fill255and156(new byte[] { 0, 0, 0 });
2.45 +
2.46 + final int ret = readShortArg(arr, 0);
2.47 + assert ret < 65000: "Value: " + ret;
2.48 + return ret;
2.49 + }
2.50 +
2.51 + @Compare public int readIntArgsMinus1andMinus100() {
2.52 + final byte[] arr = new byte[] { (byte)0, (byte)-1, (byte)-100 };
2.53 +
2.54 + assert arr[1] == -1 : "First byte: " + arr[1];
2.55 + assert arr[2] == -100 : "Second byte: " + arr[2];
2.56 +
2.57 + return readShortArg(arr, 0);
2.58 + }
2.59
2.60 @Factory
2.61 public static Object[] create() {