# HG changeset patch # User Jaroslav Tulach # Date 1358001849 -3600 # Node ID d859199a15b7b6d156b7e41d0cd5f6f3af442555 # Parent b4940ef8743882e0fa47d38beaf766faf88f94f8# Parent 7c44422713673e24e7d249ba8e7a87097d30e1c2 Merging in integer arithmetic by Martin diff -r b4940ef87438 -r d859199a15b7 emul/src/main/java/java/lang/Object.java --- a/emul/src/main/java/java/lang/Object.java Sat Jan 12 15:40:20 2013 +0100 +++ b/emul/src/main/java/java/lang/Object.java Sat Jan 12 15:44:09 2013 +0100 @@ -106,11 +106,14 @@ */ @JavaScriptBody(args = "self", body = "if (self.$hashCode) return self.$hashCode;\n" - + "var h = Math.random() * Math.pow(2, 32);\n" + + "var h = self.computeHashCode__I(self);\n" + "return self.$hashCode = h & h;" ) public native int hashCode(); + @JavaScriptBody(args = "self", body = "Math.random() * Math.pow(2, 32);") + native int computeHashCode(); + /** * Indicates whether some other object is "equal to" this one. *

diff -r b4940ef87438 -r d859199a15b7 emul/src/main/java/java/lang/String.java --- a/emul/src/main/java/java/lang/String.java Sat Jan 12 15:40:20 2013 +0100 +++ b/emul/src/main/java/java/lang/String.java Sat Jan 12 15:44:09 2013 +0100 @@ -108,10 +108,6 @@ public final class String implements java.io.Serializable, Comparable, CharSequence { - @JavaScriptOnly - /** Cache the hash code for the string */ - private int hash; // Default to 0 - /** real string to delegate to */ private Object r; @@ -1491,26 +1487,18 @@ * * @return a hash code value for this object. */ - @JavaScriptBody(args = "self", body = - "var h = 0;\n" + - "var s = self.toString();\n" + - "for (var i = 0; i < s.length; i++) {\n" + - " var high = (h >> 16) & 0xffff, low = h & 0xffff;\n" + - " h = (((((31 * high) & 0xffff) << 16) >>> 0) + (31 * low) + s.charCodeAt(i)) & 0xffffffff;\n" + - "}\n" + - "return h;\n" - ) public int hashCode() { - int h = hash; + return super.hashCode(); + } + int computeHashCode() { + int h = 0; if (h == 0 && length() > 0) { int off = offset(); - char val[] = toCharArray(); int len = length(); for (int i = 0; i < len; i++) { - h = 31*h + val[off++]; + h = 31*h + charAt(off++); } - hash = h; } return h; } @@ -2742,7 +2730,6 @@ * of this string and whose contents are initialized to contain * the character sequence represented by this string. */ - @JavaScriptBody(args = "self", body = "return self.toString().split('');") public char[] toCharArray() { char result[] = new char[length()]; getChars(0, length(), result, 0); diff -r b4940ef87438 -r d859199a15b7 vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sat Jan 12 15:40:20 2013 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sat Jan 12 15:44:09 2013 +0100 @@ -491,7 +491,7 @@ emit(out, "@1 = @2;", lmapper.setD(3), smapper.popD()); break; case opc_iadd: - emit(out, "@1 += @2;", smapper.getI(1), smapper.popI()); + emit(out, "@1 = (@1 + @2) | 0;", smapper.getI(1), smapper.popI()); break; case opc_ladd: emit(out, "@1 += @2;", smapper.getL(1), smapper.popL()); @@ -503,7 +503,7 @@ emit(out, "@1 += @2;", smapper.getD(1), smapper.popD()); break; case opc_isub: - emit(out, "@1 -= @2;", smapper.getI(1), smapper.popI()); + emit(out, "@1 = (@1 - @2) | 0;", smapper.getI(1), smapper.popI()); break; case opc_lsub: emit(out, "@1 -= @2;", smapper.getL(1), smapper.popL()); @@ -515,7 +515,7 @@ emit(out, "@1 -= @2;", smapper.getD(1), smapper.popD()); break; case opc_imul: - emit(out, "@1 *= @2;", smapper.getI(1), smapper.popI()); + emit(out, "@1 = (((@1 * (@2 >> 16)) << 16) + @1 * (@2 & 0xFFFF)) | 0;", smapper.getI(1), smapper.popI()); break; case opc_lmul: emit(out, "@1 *= @2;", smapper.getL(1), smapper.popL()); diff -r b4940ef87438 -r d859199a15b7 vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java Sat Jan 12 15:40:20 2013 +0100 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java Sat Jan 12 15:44:09 2013 +0100 @@ -39,6 +39,10 @@ return StaticUse.NON_NULL.hashCode() - StaticUse.NON_NULL.hashCode(); } + @Compare public int hashOfInt() { + return Integer.valueOf(Integer.MAX_VALUE).hashCode(); + } + @Factory public static Object[] create() { return VMTest.create(CompareHashTest.class); diff -r b4940ef87438 -r d859199a15b7 vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java Sat Jan 12 15:44:09 2013 +0100 @@ -0,0 +1,98 @@ +/** + * 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 IntegerArithmeticTest { + + private static int add(int x, int y) { + return x + y; + } + + private static int sub(int x, int y) { + return x - y; + } + + private static int mul(int x, int y) { + return x * y; + } + + private static int div(int x, int y) { + return x / y; + } + + private static int mod(int x, int y) { + return x % y; + } + + @Compare public int addOverflow() { + return add(Integer.MAX_VALUE, 1); + } + + @Compare public int subUnderflow() { + return sub(Integer.MIN_VALUE, 1); + } + + @Compare public int addMaxIntAndMaxInt() { + return add(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + @Compare public int subMinIntAndMinInt() { + return sub(Integer.MIN_VALUE, Integer.MIN_VALUE); + } + + @Compare public int multiplyMaxInt() { + return mul(Integer.MAX_VALUE, 2); + } + + @Compare public int multiplyMaxIntAndMaxInt() { + return mul(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + @Compare public int multiplyMinInt() { + return mul(Integer.MIN_VALUE, 2); + } + + @Compare public int multiplyMinIntAndMinInt() { + return mul(Integer.MIN_VALUE, Integer.MIN_VALUE); + } + + @Compare public int multiplyPrecision() { + return mul(119106029, 1103515245); + } + + @Compare public int division() { + return div(1, 2); + } + + @Compare public int divisionReminder() { + return mod(1, 2); + } + + @Factory + public static Object[] create() { + return VMTest.create(IntegerArithmeticTest.class); + } +}