# HG changeset patch # User Jaroslav Tulach # Date 1358247187 -3600 # Node ID f2f769bafeef46237b8e671b9e5c04101bf37a2f # Parent 02efb6bda7de726be9b6a29169afa04cd49be2d3# Parent 6506c5925775c038cc8d2b54f1344431bea478e7 Bringing Martin's integer, short, byte arithmetic to default branch diff -r 02efb6bda7de -r f2f769bafeef emul/src/main/java/java/lang/Number.java --- a/emul/src/main/java/java/lang/Number.java Tue Jan 15 11:44:23 2013 +0100 +++ b/emul/src/main/java/java/lang/Number.java Tue Jan 15 11:53:07 2013 +0100 @@ -25,6 +25,8 @@ package java.lang; +import org.apidesign.bck2brwsr.core.ExtraJavaScript; + /** * The abstract class Number is the superclass of classes * BigDecimal, BigInteger, @@ -46,6 +48,10 @@ * @see java.lang.Short * @since JDK1.0 */ +@ExtraJavaScript( + resource="/org/apidesign/vm4brwsr/emul/java_lang_Number.js", + processByteCode=true +) public abstract class Number implements java.io.Serializable { /** * Returns the value of the specified number as an int. diff -r 02efb6bda7de -r f2f769bafeef emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_Number.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_Number.js Tue Jan 15 11:53:07 2013 +0100 @@ -0,0 +1,9 @@ +// empty line needed here +Number.prototype.add32 = function(x) { return (this + x) | 0; }; +Number.prototype.sub32 = function(x) { return (this - x) | 0; }; +Number.prototype.mul32 = function(x) { + return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0; +}; + +Number.prototype.toInt8 = function() { return (this << 24) >> 24; }; +Number.prototype.toInt16 = function() { return (this << 16) >> 16; }; \ No newline at end of file diff -r 02efb6bda7de -r f2f769bafeef emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js --- a/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Tue Jan 15 11:44:23 2013 +0100 +++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Tue Jan 15 11:53:07 2013 +0100 @@ -2,11 +2,8 @@ vm.java_lang_String(false); // we need initialized arrays -Array.prototype.fillNulls = function() { - for(var i = 0; i < this.length; i++) this[i] = null; - return this; -}; -Array.prototype.arrtype = function(sig) { +Array.prototype.initWith = function(sig, value) { + for(var i = 0; i < this.length; i++) this[i] = value; this.jvmName = sig; return this; }; diff -r 02efb6bda7de -r f2f769bafeef vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Jan 15 11:44:23 2013 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Jan 15 11:53:07 2013 +0100 @@ -494,7 +494,7 @@ emit(out, "@1 = @2;", lmapper.setD(3), smapper.popD()); break; case opc_iadd: - emit(out, "@1 = (@1 + @2) | 0;", smapper.getI(1), smapper.popI()); + emit(out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI()); break; case opc_ladd: emit(out, "@1 += @2;", smapper.getL(1), smapper.popL()); @@ -506,7 +506,7 @@ emit(out, "@1 += @2;", smapper.getD(1), smapper.popD()); break; case opc_isub: - emit(out, "@1 = (@1 - @2) | 0;", smapper.getI(1), smapper.popI()); + emit(out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI()); break; case opc_lsub: emit(out, "@1 -= @2;", smapper.getL(1), smapper.popL()); @@ -518,7 +518,7 @@ emit(out, "@1 -= @2;", smapper.getD(1), smapper.popD()); break; case opc_imul: - emit(out, "@1 = (((@1 * (@2 >> 16)) << 16) + @1 * (@2 & 0xFFFF)) | 0;", smapper.getI(1), smapper.popI()); + emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI()); break; case opc_lmul: emit(out, "@1 *= @2;", smapper.getL(1), smapper.popL()); @@ -675,9 +675,13 @@ smapper.popD(), smapper.pushL()); break; case opc_i2b: + emit(out, "@1 = @1.toInt8();", smapper.getI(0)); + break; case opc_i2c: + out.append("{ /* number conversion */ }"); + break; case opc_i2s: - out.append("{ /* number conversion */ }"); + emit(out, "@1 = @1.toInt16();", smapper.getI(0)); break; case opc_aconst_null: emit(out, "@1 = null;", smapper.pushA()); @@ -921,7 +925,7 @@ case 11: jvmType = "[J"; break; default: throw new IllegalStateException("Array type: " + atype); } - emit(out, "@2 = new Array(@1).fillNulls().arrtype('@3');", + emit(out, "@2 = new Array(@1).initWith('@3', 0);", smapper.popI(), smapper.pushA(), jvmType); break; case opc_anewarray: { @@ -933,7 +937,7 @@ } else { typeName = "[L" + typeName + ";"; } - emit(out, "@2 = new Array(@1).fillNulls().arrtype('@3');", + emit(out, "@2 = new Array(@1).initWith('@3', null);", smapper.popI(), smapper.pushA(), typeName); break; } @@ -943,7 +947,7 @@ String typeName = jc.getClassName(type); int dim = readByte(byteCodes, ++i); out.append("{ var a0 = new Array(").append(smapper.popI()) - .append(").fillNulls().arrtype('").append(typeName).append("');"); + .append(").initWith('").append(typeName).append("', null);"); for (int d = 1; d < dim; d++) { typeName = typeName.substring(1); out.append("\n var l" + d).append(" = ") @@ -952,8 +956,8 @@ append(" < a" + (d - 1)). append(".length; i" + d).append("++) {"); out.append("\n var a" + d). - append (" = new Array(l" + d).append(").fillNulls().arrtype('") - .append(typeName).append("');"); + append (" = new Array(l" + d).append(").initWith('") + .append(typeName).append("', null);"); out.append("\n a" + (d - 1)).append("[i" + d).append("] = a" + d). append(";"); } diff -r 02efb6bda7de -r f2f769bafeef vm/src/test/java/org/apidesign/vm4brwsr/Array.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Tue Jan 15 11:44:23 2013 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Tue Jan 15 11:53:07 2013 +0100 @@ -98,6 +98,11 @@ return sum; } + public static int sum(int size) { + int[] arr = new int[size]; + return arr[0] + arr[1]; + } + static void arraycopy(char[] value, int srcBegin, char[] dst, int dstBegin, int count) { while (count-- > 0) { dst[dstBegin++] = value[srcBegin++]; diff -r 02efb6bda7de -r f2f769bafeef vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Tue Jan 15 11:44:23 2013 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Tue Jan 15 11:53:07 2013 +0100 @@ -27,6 +27,11 @@ * @author Jaroslav Tulach */ public class ArrayTest { + @Test public void intArrayShouldBeFilledWithZeroes() throws Exception { + assertExec("0 + 0", Array.class, "sum__II", + Double.valueOf(0), 2 + ); + } @Test public void verifySimpleIntOperation() throws Exception { assertExec("CheckTheSum", Array.class, "simple__IZ", Double.valueOf(15), false diff -r 02efb6bda7de -r f2f769bafeef vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java Tue Jan 15 11:53:07 2013 +0100 @@ -0,0 +1,102 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ByteArithmeticTest { + + private static byte add(byte x, byte y) { + return (byte)(x + y); + } + + private static byte sub(byte x, byte y) { + return (byte)(x - y); + } + + private static byte mul(byte x, byte y) { + return (byte)(x * y); + } + + private static byte div(byte x, byte y) { + return (byte)(x / y); + } + + private static byte mod(byte x, byte y) { + return (byte)(x % y); + } + + @Compare public byte conversion() { + return (byte)123456; + } + + @Compare public byte addOverflow() { + return add(Byte.MAX_VALUE, (byte)1); + } + + @Compare public byte subUnderflow() { + return sub(Byte.MIN_VALUE, (byte)1); + } + + @Compare public byte addMaxByteAndMaxByte() { + return add(Byte.MAX_VALUE, Byte.MAX_VALUE); + } + + @Compare public byte subMinByteAndMinByte() { + return sub(Byte.MIN_VALUE, Byte.MIN_VALUE); + } + + @Compare public byte multiplyMaxByte() { + return mul(Byte.MAX_VALUE, (byte)2); + } + + @Compare public byte multiplyMaxByteAndMaxByte() { + return mul(Byte.MAX_VALUE, Byte.MAX_VALUE); + } + + @Compare public byte multiplyMinByte() { + return mul(Byte.MIN_VALUE, (byte)2); + } + + @Compare public byte multiplyMinByteAndMinByte() { + return mul(Byte.MIN_VALUE, Byte.MIN_VALUE); + } + + @Compare public byte multiplyPrecision() { + return mul((byte)17638, (byte)1103); + } + + @Compare public byte division() { + return div((byte)1, (byte)2); + } + + @Compare public byte divisionReminder() { + return mod((byte)1, (byte)2); + } + + @Factory + public static Object[] create() { + return VMTest.create(ByteArithmeticTest.class); + } +} diff -r 02efb6bda7de -r f2f769bafeef vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Tue Jan 15 11:44:23 2013 +0100 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Tue Jan 15 11:53:07 2013 +0100 @@ -90,6 +90,11 @@ return "Hello".matches("Hell"); } + @Compare public String emptyCharArray() { + char[] arr = new char[10]; + return new String(arr); + } + @Compare public String variousCharacterTests() throws Exception { StringBuilder sb = new StringBuilder(); diff -r 02efb6bda7de -r f2f769bafeef vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java Tue Jan 15 11:44:23 2013 +0100 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java Tue Jan 15 11:53:07 2013 +0100 @@ -91,6 +91,25 @@ return mod(1, 2); } + @Compare public int sumTwoDimensions() { + int[][] matrix = createMatrix(4, 3); + int sum = 0; + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[i].length; j++) { + sum += matrix[i][j]; + } + } + return sum; + } + + static int[][] createMatrix(int x, int y) { + int[][] m = new int[x][y]; + for (int i = 0; i < Math.min(x, y); i++) { + m[i][i] = i; + } + return m; + } + @Factory public static Object[] create() { return VMTest.create(IntegerArithmeticTest.class); diff -r 02efb6bda7de -r f2f769bafeef vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java Tue Jan 15 11:53:07 2013 +0100 @@ -0,0 +1,102 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ShortArithmeticTest { + + private static short add(short x, short y) { + return (short)(x + y); + } + + private static short sub(short x, short y) { + return (short)(x - y); + } + + private static short mul(short x, short y) { + return (short)(x * y); + } + + private static short div(short x, short y) { + return (short)(x / y); + } + + private static short mod(short x, short y) { + return (short)(x % y); + } + + @Compare public short conversion() { + return (short)123456; + } + + @Compare public short addOverflow() { + return add(Short.MAX_VALUE, (short)1); + } + + @Compare public short subUnderflow() { + return sub(Short.MIN_VALUE, (short)1); + } + + @Compare public short addMaxShortAndMaxShort() { + return add(Short.MAX_VALUE, Short.MAX_VALUE); + } + + @Compare public short subMinShortAndMinShort() { + return sub(Short.MIN_VALUE, Short.MIN_VALUE); + } + + @Compare public short multiplyMaxShort() { + return mul(Short.MAX_VALUE, (short)2); + } + + @Compare public short multiplyMaxShortAndMaxShort() { + return mul(Short.MAX_VALUE, Short.MAX_VALUE); + } + + @Compare public short multiplyMinShort() { + return mul(Short.MIN_VALUE, (short)2); + } + + @Compare public short multiplyMinShortAndMinShort() { + return mul(Short.MIN_VALUE, Short.MIN_VALUE); + } + + @Compare public short multiplyPrecision() { + return mul((short)17638, (short)1103); + } + + @Compare public short division() { + return div((short)1, (short)2); + } + + @Compare public short divisionReminder() { + return mod((short)1, (short)2); + } + + @Factory + public static Object[] create() { + return VMTest.create(ShortArithmeticTest.class); + } +}