1.1 --- a/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Wed Jan 30 09:27:53 2013 +0100
1.2 +++ b/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Wed Jan 30 22:23:21 2013 +0100
1.3 @@ -8,6 +8,8 @@
1.4 Number.prototype.toInt8 = function() { return (this << 24) >> 24; };
1.5 Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
1.6
1.7 +var __m32 = 0xFFFFFFFF;
1.8 +
1.9 Number.prototype.next32 = function(low) {
1.10 if (this === 0) {
1.11 return low;
1.12 @@ -18,15 +20,15 @@
1.13 };
1.14
1.15 Number.prototype.high32 = function() {
1.16 - return this.hi ? this.hi : (Math.floor(this / 0xFFFFFFFF)) | 0;
1.17 + return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0;
1.18 };
1.19 Number.prototype.toInt32 = function() { return this | 0; };
1.20 Number.prototype.toFP = function() {
1.21 - return this.hi ? this.hi * 0xFFFFFFFF + this : this;
1.22 + return this.hi ? this.hi * (__m32+1) + this : this;
1.23 };
1.24 Number.prototype.toLong = function() {
1.25 - var hi = (this > 0xFFFFFFFF) ? (Math.floor(this / 0xFFFFFFFF)) | 0 : 0;
1.26 - return hi.next32(this % 0xFFFFFFFF);
1.27 + var hi = (this > __m32) ? (Math.floor(this / (__m32+1))) | 0 : 0;
1.28 + return hi.next32(this % (__m32+1));
1.29 };
1.30
1.31 Number.prototype.toExactString = function() {
1.32 @@ -59,36 +61,58 @@
1.33 Number.prototype.add64 = function(x) {
1.34 var low = this + x;
1.35 carry = 0;
1.36 - if (low > 0xFFFFFFFF) {
1.37 + if (low > __m32) {
1.38 carry = 1;
1.39 - low -= 0xFFFFFFFF; // should not here be also -1?
1.40 + low -= (__m32+1);
1.41 }
1.42 - var hi = (this.high32() + x.high32() + carry) & 0xFFFFFFFF;
1.43 + var hi = (this.high32() + x.high32() + carry) | 0;
1.44 return hi.next32(low);
1.45 };
1.46
1.47 Number.prototype.div64 = function(x) {
1.48 var low = Math.floor(this.toFP() / x.toFP()); // TODO: not exact enough
1.49 - if (low > 0xFFFFFFFF) {
1.50 - var hi = Math.floor(low / 0xFFFFFFFF) | 0;
1.51 - return hi.next32(low % 0xFFFFFFFF);
1.52 + if (low > __m32) {
1.53 + var hi = Math.floor(low / (__m32+1)) | 0;
1.54 + return hi.next32(low % (__m32+1));
1.55 }
1.56 return low;
1.57 };
1.58
1.59 +Number.prototype.and64 = function(x) {
1.60 + var low = this & x;
1.61 + if (this.hi && x.hi) {
1.62 + var hi = this.hi & x.hi;
1.63 + return hi.next32(low);
1.64 + };
1.65 + return low;
1.66 +};
1.67 +
1.68 Number.prototype.shl64 = function(x) {
1.69 if (x > 32) {
1.70 var hi = (this << (x - 32)) & 0xFFFFFFFF;
1.71 return hi.next32(0);
1.72 } else {
1.73 var hi = (this.high32() << x) & 0xFFFFFFFF;
1.74 - var low_reminder = this >> x;
1.75 + var low_reminder = this >> (32 - x);
1.76 hi |= low_reminder;
1.77 var low = this << x;
1.78 return hi.next32(low);
1.79 }
1.80 };
1.81
1.82 +Number.prototype.shr64 = function(x) {
1.83 + if (x > 32) {
1.84 + var low = (this.high32() >> (x - 32)) & 0xFFFFFFFF;
1.85 + return low;
1.86 + } else {
1.87 + var low = (this >> x) & 0xFFFFFFFF;
1.88 + var hi_reminder = (this.high32() << (32 - x)) >> (32 - x);
1.89 + low |= hi_reminder;
1.90 + var hi = this.high32() >> x;
1.91 + return hi.next32(low);
1.92 + }
1.93 +};
1.94 +
1.95 Number.prototype.compare64 = function(x) {
1.96 if (this.hi == x.hi) {
1.97 return (this == x) ? 0 : ((this < x) ? -1 : 1);
2.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Jan 30 09:27:53 2013 +0100
2.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Jan 30 22:23:21 2013 +0100
2.3 @@ -582,7 +582,7 @@
2.4 emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI());
2.5 break;
2.6 case opc_land:
2.7 - emit(out, "@1 &= @2;", smapper.getL(1), smapper.popL());
2.8 + emit(out, "@1 = @1.and64(@2);", smapper.getL(1), smapper.popL());
2.9 break;
2.10 case opc_ior:
2.11 emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI());
2.12 @@ -618,7 +618,7 @@
2.13 emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI());
2.14 break;
2.15 case opc_lshr:
2.16 - emit(out, "@1 >>= @2;", smapper.getL(1), smapper.popI());
2.17 + emit(out, "@1 = @1.shr64(@2);", smapper.getL(1), smapper.popI());
2.18 break;
2.19 case opc_iushr:
2.20 emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI());
3.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Wed Jan 30 09:27:53 2013 +0100
3.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Wed Jan 30 22:23:21 2013 +0100
3.3 @@ -144,6 +144,13 @@
3.4 );
3.5 }
3.6
3.7 + @Test public void longConversion() throws Exception {
3.8 + assertExec("Long from cPool",
3.9 + Numbers.class, "conversionL__J",
3.10 + Double.valueOf(Long.MAX_VALUE)
3.11 + );
3.12 + }
3.13 +
3.14 private static CharSequence codeSeq;
3.15 private static Invocable code;
3.16
4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Wed Jan 30 09:27:53 2013 +0100
4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Wed Jan 30 22:23:21 2013 +0100
4.3 @@ -67,4 +67,28 @@
4.4 static String floatToString() {
4.5 return new Float(7.0).toString().toString();
4.6 }
4.7 +
4.8 + public static long conversionL() {
4.9 + return Long.MAX_VALUE;
4.10 + }
4.11 +
4.12 + public static long addL(long x, long y) {
4.13 + return (x + y);
4.14 + }
4.15 +
4.16 + public static long subL(long x, long y) {
4.17 + return (x - y);
4.18 + }
4.19 +
4.20 + public static long mulL(long x, long y) {
4.21 + return (x * y);
4.22 + }
4.23 +
4.24 + public static long divL(long x, long y) {
4.25 + return (x / y);
4.26 + }
4.27 +
4.28 + public static long modL(long x, long y) {
4.29 + return (x % y);
4.30 + }
4.31 }
5.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/TestUtils.java Wed Jan 30 09:27:53 2013 +0100
5.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/TestUtils.java Wed Jan 30 22:23:21 2013 +0100
5.3 @@ -47,6 +47,7 @@
5.4 // in case of Long it is necessary convert it to number
5.5 // since the Long is represented by two numbers in JavaScript
5.6 try {
5.7 + ret = code.invokeMethod(ret, "toFP");
5.8 ret = code.invokeFunction("Number", ret);
5.9 } catch (ScriptException ex) {
5.10 fail("Conversion to number failed in " + StaticMethodTest.dumpJS(codeSeq), ex);