# HG changeset patch # User Martin Soch # Date 1359581001 -3600 # Node ID e3f671b50e93048b444feaa04232c064b62fba7d # Parent 9e4d0019a9ebe82437adbbc4e946b636d6e0f2ac Long tests moved (temporarily) among VM tests Long conversion test already passing Long version of & and >> operators added diff -r 9e4d0019a9eb -r e3f671b50e93 emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js --- a/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Wed Jan 30 09:27:53 2013 +0100 +++ b/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Wed Jan 30 22:23:21 2013 +0100 @@ -8,6 +8,8 @@ Number.prototype.toInt8 = function() { return (this << 24) >> 24; }; Number.prototype.toInt16 = function() { return (this << 16) >> 16; }; +var __m32 = 0xFFFFFFFF; + Number.prototype.next32 = function(low) { if (this === 0) { return low; @@ -18,15 +20,15 @@ }; Number.prototype.high32 = function() { - return this.hi ? this.hi : (Math.floor(this / 0xFFFFFFFF)) | 0; + return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0; }; Number.prototype.toInt32 = function() { return this | 0; }; Number.prototype.toFP = function() { - return this.hi ? this.hi * 0xFFFFFFFF + this : this; + return this.hi ? this.hi * (__m32+1) + this : this; }; Number.prototype.toLong = function() { - var hi = (this > 0xFFFFFFFF) ? (Math.floor(this / 0xFFFFFFFF)) | 0 : 0; - return hi.next32(this % 0xFFFFFFFF); + var hi = (this > __m32) ? (Math.floor(this / (__m32+1))) | 0 : 0; + return hi.next32(this % (__m32+1)); }; Number.prototype.toExactString = function() { @@ -59,36 +61,58 @@ Number.prototype.add64 = function(x) { var low = this + x; carry = 0; - if (low > 0xFFFFFFFF) { + if (low > __m32) { carry = 1; - low -= 0xFFFFFFFF; // should not here be also -1? + low -= (__m32+1); } - var hi = (this.high32() + x.high32() + carry) & 0xFFFFFFFF; + var hi = (this.high32() + x.high32() + carry) | 0; return hi.next32(low); }; Number.prototype.div64 = function(x) { var low = Math.floor(this.toFP() / x.toFP()); // TODO: not exact enough - if (low > 0xFFFFFFFF) { - var hi = Math.floor(low / 0xFFFFFFFF) | 0; - return hi.next32(low % 0xFFFFFFFF); + if (low > __m32) { + var hi = Math.floor(low / (__m32+1)) | 0; + return hi.next32(low % (__m32+1)); } return low; }; +Number.prototype.and64 = function(x) { + var low = this & x; + if (this.hi && x.hi) { + var hi = this.hi & x.hi; + return hi.next32(low); + }; + return low; +}; + Number.prototype.shl64 = function(x) { if (x > 32) { var hi = (this << (x - 32)) & 0xFFFFFFFF; return hi.next32(0); } else { var hi = (this.high32() << x) & 0xFFFFFFFF; - var low_reminder = this >> x; + var low_reminder = this >> (32 - x); hi |= low_reminder; var low = this << x; return hi.next32(low); } }; +Number.prototype.shr64 = function(x) { + if (x > 32) { + var low = (this.high32() >> (x - 32)) & 0xFFFFFFFF; + return low; + } else { + var low = (this >> x) & 0xFFFFFFFF; + var hi_reminder = (this.high32() << (32 - x)) >> (32 - x); + low |= hi_reminder; + var hi = this.high32() >> x; + return hi.next32(low); + } +}; + Number.prototype.compare64 = function(x) { if (this.hi == x.hi) { return (this == x) ? 0 : ((this < x) ? -1 : 1); diff -r 9e4d0019a9eb -r e3f671b50e93 vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Jan 30 09:27:53 2013 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Jan 30 22:23:21 2013 +0100 @@ -582,7 +582,7 @@ emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI()); break; case opc_land: - emit(out, "@1 &= @2;", smapper.getL(1), smapper.popL()); + emit(out, "@1 = @1.and64(@2);", smapper.getL(1), smapper.popL()); break; case opc_ior: emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI()); @@ -618,7 +618,7 @@ emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI()); break; case opc_lshr: - emit(out, "@1 >>= @2;", smapper.getL(1), smapper.popI()); + emit(out, "@1 = @1.shr64(@2);", smapper.getL(1), smapper.popI()); break; case opc_iushr: emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI()); diff -r 9e4d0019a9eb -r e3f671b50e93 vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Wed Jan 30 09:27:53 2013 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Wed Jan 30 22:23:21 2013 +0100 @@ -144,6 +144,13 @@ ); } + @Test public void longConversion() throws Exception { + assertExec("Long from cPool", + Numbers.class, "conversionL__J", + Double.valueOf(Long.MAX_VALUE) + ); + } + private static CharSequence codeSeq; private static Invocable code; diff -r 9e4d0019a9eb -r e3f671b50e93 vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Wed Jan 30 09:27:53 2013 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Wed Jan 30 22:23:21 2013 +0100 @@ -67,4 +67,28 @@ static String floatToString() { return new Float(7.0).toString().toString(); } + + public static long conversionL() { + return Long.MAX_VALUE; + } + + public static long addL(long x, long y) { + return (x + y); + } + + public static long subL(long x, long y) { + return (x - y); + } + + public static long mulL(long x, long y) { + return (x * y); + } + + public static long divL(long x, long y) { + return (x / y); + } + + public static long modL(long x, long y) { + return (x % y); + } } diff -r 9e4d0019a9eb -r e3f671b50e93 vm/src/test/java/org/apidesign/vm4brwsr/TestUtils.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/TestUtils.java Wed Jan 30 09:27:53 2013 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/TestUtils.java Wed Jan 30 22:23:21 2013 +0100 @@ -47,6 +47,7 @@ // in case of Long it is necessary convert it to number // since the Long is represented by two numbers in JavaScript try { + ret = code.invokeMethod(ret, "toFP"); ret = code.invokeFunction("Number", ret); } catch (ScriptException ex) { fail("Conversion to number failed in " + StaticMethodTest.dumpJS(codeSeq), ex);