Merging in long arithmetic, otherwise the zip support won't work emul
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 13:07:22 +0100
branchemul
changeset 695dbcd1a21f3f8
parent 694 0d277415ed02
parent 689 f87c33d2fa7b
child 701 bfb3f72249de
Merging in long arithmetic, otherwise the zip support won't work
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
     1.1 --- a/emul/mini/src/main/java/java/lang/Character.java	Thu Feb 07 12:58:12 2013 +0100
     1.2 +++ b/emul/mini/src/main/java/java/lang/Character.java	Thu Feb 07 13:07:22 2013 +0100
     1.3 @@ -2193,6 +2193,10 @@
     1.4       * @see     Character#isDigit(int)
     1.5       * @since   1.5
     1.6       */
     1.7 +    @JavaScriptBody(args = { "codePoint", "radix" }, body=
     1.8 +        "var x = parseInt(String.fromCharCode(codePoint), radix);\n"
     1.9 +      + "return isNaN(x) ? -1 : x;"
    1.10 +    )
    1.11      public static int digit(int codePoint, int radix) {
    1.12          throw new UnsupportedOperationException();
    1.13      }
     2.1 --- a/emul/mini/src/main/java/java/lang/Long.java	Thu Feb 07 12:58:12 2013 +0100
     2.2 +++ b/emul/mini/src/main/java/java/lang/Long.java	Thu Feb 07 13:07:22 2013 +0100
     2.3 @@ -262,7 +262,7 @@
     2.4       * @param   i   a {@code long} to be converted.
     2.5       * @return  a string representation of the argument in base&nbsp;10.
     2.6       */
     2.7 -    @JavaScriptBody(args = "i", body = "return i.toString();")
     2.8 +    @JavaScriptBody(args = "i", body = "return i.toExactString();")
     2.9      public static String toString(long i) {
    2.10          if (i == Long.MIN_VALUE)
    2.11              return "-9223372036854775808";
     3.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Thu Feb 07 12:58:12 2013 +0100
     3.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Thu Feb 07 13:07:22 2013 +0100
     3.3 @@ -54,7 +54,7 @@
     3.4      )
     3.5      public static native byte[] expandArray(byte[] arr, int expectedSize);
     3.6  
     3.7 -    @JavaScriptBody(args = {}, body = "new Date().getMilliseconds();")
     3.8 +    @JavaScriptBody(args = {}, body = "return new Date().getMilliseconds();")
     3.9      public static native long currentTimeMillis();
    3.10      
    3.11      public static long nanoTime() {
     4.1 --- a/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Thu Feb 07 12:58:12 2013 +0100
     4.2 +++ b/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Thu Feb 07 13:07:22 2013 +0100
     4.3 @@ -6,4 +6,509 @@
     4.4  };
     4.5  
     4.6  Number.prototype.toInt8 = function()  { return (this << 24) >> 24; };
     4.7 -Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
     4.8 \ No newline at end of file
     4.9 +Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
    4.10 +
    4.11 +var __m32 = 0xFFFFFFFF;
    4.12 +
    4.13 +Number.prototype.next32 = function(low) {
    4.14 +  if (this === 0) {
    4.15 +    return low;
    4.16 +  }
    4.17 +  var l = new Number(low);
    4.18 +  l.hi = this | 0;
    4.19 +  return l;
    4.20 +};
    4.21 +
    4.22 +Number.prototype.high32 = function() { 
    4.23 +    return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0;
    4.24 +};
    4.25 +Number.prototype.toInt32 = function() { return this | 0; };
    4.26 +Number.prototype.toFP = function() {
    4.27 +    return this.hi ? this.hi * (__m32+1) + this : this;
    4.28 +};
    4.29 +Number.prototype.toLong = function() {
    4.30 +    var hi = (this > __m32) ? (Math.floor(this / (__m32+1))) | 0 : 0;
    4.31 +    return hi.next32(Math.floor(this % (__m32+1)));
    4.32 +};
    4.33 +
    4.34 +Number.prototype.toExactString = function() {
    4.35 +    if (this.hi) {
    4.36 +        var res = 0;
    4.37 +        var a = [ 6,9,2,7,6,9,4,9,2,4 ];
    4.38 +        var s = '';
    4.39 +        var digit;
    4.40 +        var neg = this.hi < 0;
    4.41 +        if (neg) {
    4.42 +            var x = this.neg64();
    4.43 +            var hi = x.hi;
    4.44 +            var low = x;
    4.45 +        } else {
    4.46 +            var hi = this.hi;
    4.47 +            var low = this;
    4.48 +        }
    4.49 +        for (var i = 0; i < a.length; i++) {
    4.50 +            res += hi * a[i];
    4.51 +            var low_digit = low % 10;
    4.52 +            digit = (res % 10) + low_digit;
    4.53 +
    4.54 +            low = Math.floor(low / 10);
    4.55 +            res = Math.floor(res / 10);
    4.56 +
    4.57 +            if (digit >= 10) {
    4.58 +                digit -= 10;
    4.59 +                res++;
    4.60 +            }
    4.61 +            s = String(digit).concat(s);
    4.62 +        }
    4.63 +        return (neg ? '-' : '').concat(res).concat(s);
    4.64 +    }
    4.65 +    return String(this);
    4.66 +};
    4.67 +
    4.68 +Number.prototype.add64 = function(x) {
    4.69 +    var low = this + x;
    4.70 +    carry = 0;
    4.71 +    if (low > __m32) {
    4.72 +        carry = 1;
    4.73 +        low -= (__m32+1);
    4.74 +    }
    4.75 +    var hi = (this.high32() + x.high32() + carry) | 0;
    4.76 +    return hi.next32(low);
    4.77 +};
    4.78 +
    4.79 +Number.prototype.sub64 = function(x) {
    4.80 +    var low = this - x;
    4.81 +    carry = 0;
    4.82 +    if (low < 0) {
    4.83 +        carry = 1;
    4.84 +        low += (__m32+1);
    4.85 +    }
    4.86 +    var hi = (this.high32() - x.high32() - carry) | 0;
    4.87 +    return hi.next32(low);
    4.88 +};
    4.89 +
    4.90 +Number.prototype.mul64 = function(x) {
    4.91 +    var low = this.mul32(x);
    4.92 +    low += (low < 0) ? (__m32+1) : 0;
    4.93 +    // first count upper 32 bits of (this.low * x.low)
    4.94 +    var hi_hi = 0;
    4.95 +    var hi_low = 0;
    4.96 +    var m = 1;
    4.97 +    for (var i = 0; i < 32; i++) {
    4.98 +        if (x & m) {
    4.99 +            hi_hi += this >>> 16;
   4.100 +            hi_low += this & 0xFFFF
   4.101 +        }
   4.102 +        hi_low >>= 1;
   4.103 +        hi_low += (hi_hi & 1) ? 0x8000 : 0;
   4.104 +        hi_hi >>= 1;
   4.105 +        m <<= 1;
   4.106 +    }
   4.107 +    var hi = (hi_hi << 16) + hi_low;
   4.108 +    
   4.109 +    var m1 = this.high32().mul32(x);
   4.110 +    var m2 = this.mul32(x.high32());
   4.111 +    hi = hi.add32(m1).add32(m2);
   4.112 +    
   4.113 +    return hi.next32(low);
   4.114 +};
   4.115 +
   4.116 +Number.prototype.and64 = function(x) {
   4.117 +    var low = this & x;
   4.118 +    low += (low < 0) ? (__m32+1) : 0;
   4.119 +    if (this.hi && x.hi) {
   4.120 +        var hi = this.hi & x.hi;
   4.121 +        return hi.next32(low);
   4.122 +    };
   4.123 +    return low;
   4.124 +};
   4.125 +
   4.126 +Number.prototype.or64 = function(x) {
   4.127 +    var low = this | x;
   4.128 +    low += (low < 0) ? (__m32+1) : 0;
   4.129 +    if (this.hi || x.hi) {
   4.130 +        var hi = this.hi | x.hi;
   4.131 +        return hi.next32(low);
   4.132 +    };
   4.133 +    return low;
   4.134 +};
   4.135 +
   4.136 +Number.prototype.xor64 = function(x) {
   4.137 +    var low = this ^ x;
   4.138 +    low += (low < 0) ? (__m32+1) : 0;
   4.139 +    if (this.hi || x.hi) {
   4.140 +        var hi = this.hi ^ x.hi;
   4.141 +        return hi.next32(low);
   4.142 +    };
   4.143 +    return low;
   4.144 +};
   4.145 +
   4.146 +Number.prototype.shl64 = function(x) {
   4.147 +    if (x >= 32) {
   4.148 +        var hi = this << (x - 32);
   4.149 +        return hi.next32(0);
   4.150 +    } else {
   4.151 +        var hi = this.high32() << x;
   4.152 +        var low_reminder = this >> (32 - x);
   4.153 +        hi |= low_reminder;
   4.154 +        var low = this << x;
   4.155 +        low += (low < 0) ? (__m32+1) : 0;
   4.156 +        return hi.next32(low);
   4.157 +    }
   4.158 +};
   4.159 +
   4.160 +Number.prototype.shr64 = function(x) {
   4.161 +    if (x >= 32) {
   4.162 +        var low = this.high32() >> (x - 32);
   4.163 +        low += (low < 0) ? (__m32+1) : 0;
   4.164 +        return low;
   4.165 +    } else {
   4.166 +        var low = this >> x;
   4.167 +        var hi_reminder = this.high32() << (32 - x);
   4.168 +        low |= hi_reminder;
   4.169 +        low += (low < 0) ? (__m32+1) : 0;
   4.170 +        var hi = this.high32() >> x;
   4.171 +        return hi.next32(low);
   4.172 +    }
   4.173 +};
   4.174 +
   4.175 +Number.prototype.ushr64 = function(x) {
   4.176 +    if (x >= 32) {
   4.177 +        var low = this.high32() >>> (x - 32);
   4.178 +        low += (low < 0) ? (__m32+1) : 0;
   4.179 +        return low;
   4.180 +    } else {
   4.181 +        var low = this >>> x;
   4.182 +        var hi_reminder = this.high32() << (32 - x);
   4.183 +        low |= hi_reminder;
   4.184 +        low += (low < 0) ? (__m32+1) : 0;
   4.185 +        var hi = this.high32() >>> x;
   4.186 +        return hi.next32(low);
   4.187 +    }
   4.188 +};
   4.189 +
   4.190 +Number.prototype.compare64 = function(x) {
   4.191 +    if (this.high32() === x.high32()) {
   4.192 +        return (this < x) ? -1 : ((this > x) ? 1 : 0);
   4.193 +    }
   4.194 +    return (this.high32() < x.high32()) ? -1 : 1;
   4.195 +};
   4.196 +
   4.197 +Number.prototype.neg64 = function() {
   4.198 +    var hi = this.high32();
   4.199 +    var low = this;
   4.200 +    if ((hi === 0) && (low < 0)) { return -low; }
   4.201 +    hi = ~hi;
   4.202 +    low = ~low;
   4.203 +    low += (low < 0) ? (__m32+1) : 0;
   4.204 +    var ret = hi.next32(low);
   4.205 +    return ret.add64(1);
   4.206 +};
   4.207 +
   4.208 +(function(numberPrototype) {
   4.209 +    function __Int64(hi32, lo32) {
   4.210 +        this.hi32 = hi32 | 0;
   4.211 +        this.lo32 = lo32 | 0;
   4.212 +
   4.213 +        this.get32 = function(bitIndex) {
   4.214 +            var v0;
   4.215 +            var v1;
   4.216 +            bitIndex += 32;
   4.217 +            var selector = bitIndex >>> 5;
   4.218 +            switch (selector) {
   4.219 +                case 0:
   4.220 +                    v0 = 0;
   4.221 +                    v1 = this.lo32;
   4.222 +                    break;
   4.223 +                case 1:
   4.224 +                    v0 = this.lo32;
   4.225 +                    v1 = this.hi32;
   4.226 +                    break;
   4.227 +                case 2:
   4.228 +                    v0 = this.hi32;
   4.229 +                    v1 = 0;
   4.230 +                    break
   4.231 +                default:
   4.232 +                    return 0;
   4.233 +            }
   4.234 +
   4.235 +            var shift = bitIndex & 31;
   4.236 +            if (shift === 0) {
   4.237 +                return v0;
   4.238 +            }
   4.239 +
   4.240 +            return (v1 << (32 - shift)) | (v0 >>> shift);
   4.241 +        }
   4.242 +
   4.243 +        this.get16 = function(bitIndex) {
   4.244 +            return this.get32(bitIndex) & 0xffff;
   4.245 +        }
   4.246 +
   4.247 +        this.set16 = function(bitIndex, value) {
   4.248 +            bitIndex += 32;
   4.249 +            var shift = bitIndex & 15;
   4.250 +            var svalue = (value & 0xffff) << shift; 
   4.251 +            var smask = 0xffff << shift;
   4.252 +            var selector = bitIndex >>> 4;
   4.253 +            switch (selector) {
   4.254 +                case 0:
   4.255 +                    break;
   4.256 +                case 1:
   4.257 +                    this.lo32 = (this.lo32 & ~(smask >>> 16))
   4.258 +                                    | (svalue >>> 16);
   4.259 +                    break;
   4.260 +                case 2:
   4.261 +                    this.lo32 = (this.lo32 & ~smask) | svalue;
   4.262 +                    break;
   4.263 +                case 3:
   4.264 +                    this.lo32 = (this.lo32 & ~(smask << 16))
   4.265 +                                    | (svalue << 16);
   4.266 +                    this.hi32 = (this.hi32 & ~(smask >>> 16))
   4.267 +                                    | (svalue >>> 16);
   4.268 +                    break;
   4.269 +                case 4:
   4.270 +                    this.hi32 = (this.hi32 & ~smask) | svalue;
   4.271 +                    break;
   4.272 +                case 5:
   4.273 +                    this.hi32 = (this.hi32 & ~(smask << 16))
   4.274 +                                    | (svalue << 16);
   4.275 +                    break;
   4.276 +            }
   4.277 +        }
   4.278 +
   4.279 +        this.getDigit = function(index, shift) {
   4.280 +            return this.get16((index << 4) - shift);
   4.281 +        }
   4.282 +
   4.283 +        this.getTwoDigits = function(index, shift) {
   4.284 +            return this.get32(((index - 1) << 4) - shift);
   4.285 +        }
   4.286 +
   4.287 +        this.setDigit = function(index, shift, value) {
   4.288 +            this.set16((index << 4) - shift, value);
   4.289 +        }
   4.290 +
   4.291 +        this.countSignificantDigits = function() {
   4.292 +            var sd;
   4.293 +            var remaining;
   4.294 +
   4.295 +            if (this.hi32 === 0) {
   4.296 +                if (this.lo32 === 0) {
   4.297 +                    return 0;
   4.298 +                }
   4.299 +
   4.300 +                sd = 2;
   4.301 +                remaining = this.lo32;
   4.302 +            } else {
   4.303 +                sd = 4;
   4.304 +                remaining = this.hi32;
   4.305 +            }
   4.306 +
   4.307 +            if (remaining < 0) {
   4.308 +                return sd;
   4.309 +            }
   4.310 +
   4.311 +            return (remaining < 65536) ? sd - 1 : sd;
   4.312 +        }
   4.313 +        
   4.314 +        this.toNumber = function() {
   4.315 +            var lo32 = this.lo32;
   4.316 +            if (lo32 < 0) {
   4.317 +                lo32 += 0x100000000;
   4.318 +            }
   4.319 +
   4.320 +            return this.hi32.next32(lo32);
   4.321 +        }
   4.322 +    }
   4.323 +
   4.324 +    function __countLeadingZeroes16(number) {
   4.325 +        var nlz = 0;
   4.326 +
   4.327 +        if (number < 256) {
   4.328 +            nlz += 8;
   4.329 +            number <<= 8;
   4.330 +        }
   4.331 +
   4.332 +        if (number < 4096) {
   4.333 +            nlz += 4;
   4.334 +            number <<= 4;
   4.335 +        }
   4.336 +
   4.337 +        if (number < 16384) {
   4.338 +            nlz += 2;
   4.339 +            number <<= 2;
   4.340 +        }
   4.341 +
   4.342 +        return (number < 32768) ? nlz + 1 : nlz;
   4.343 +    }
   4.344 +    
   4.345 +    // q = u / v; r = u - q * v;
   4.346 +    // v != 0
   4.347 +    function __div64(q, r, u, v) {
   4.348 +        var m = u.countSignificantDigits();
   4.349 +        var n = v.countSignificantDigits();
   4.350 +
   4.351 +        q.hi32 = q.lo32 = 0;
   4.352 +
   4.353 +        if (n === 1) {
   4.354 +            // v has single digit
   4.355 +            var vd = v.getDigit(0, 0);
   4.356 +            var carry = 0;
   4.357 +            for (var i = m - 1; i >= 0; --i) {
   4.358 +                var ui = (carry << 16) | u.getDigit(i, 0);
   4.359 +                if (ui < 0) {
   4.360 +                    ui += 0x100000000;
   4.361 +                }
   4.362 +                var qi = (ui / vd) | 0;
   4.363 +                q.setDigit(i, 0, qi);
   4.364 +                carry = ui - qi * vd;
   4.365 +            }
   4.366 +
   4.367 +            r.hi32 = 0;
   4.368 +            r.lo32 = carry;
   4.369 +            return;
   4.370 +        }
   4.371 +
   4.372 +        r.hi32 = u.hi32;  
   4.373 +        r.lo32 = u.lo32;
   4.374 +
   4.375 +        if (m < n) {
   4.376 +            return;
   4.377 +        }
   4.378 +
   4.379 +        // Normalize
   4.380 +        var nrm = __countLeadingZeroes16(v.getDigit(n - 1, 0));
   4.381 +
   4.382 +        var vd1 = v.getDigit(n - 1, nrm);                
   4.383 +        var vd0 = v.getDigit(n - 2, nrm);
   4.384 +        for (var j = m - n; j >= 0; --j) {
   4.385 +            // Calculate qj estimate
   4.386 +            var ud21 = r.getTwoDigits(j + n, nrm);
   4.387 +            var ud2 = ud21 >>> 16;
   4.388 +            if (ud21 < 0) {
   4.389 +                ud21 += 0x100000000;
   4.390 +            }
   4.391 +
   4.392 +            var qest = (ud2 === vd1) ? 0xFFFF : ((ud21 / vd1) | 0);
   4.393 +            var rest = ud21 - qest * vd1;
   4.394 +
   4.395 +            // 0 <= (qest - qj) <= 2
   4.396 +
   4.397 +            // Refine qj estimate
   4.398 +            var ud0 = r.getDigit(j + n - 2, nrm);
   4.399 +            while ((qest * vd0) > ((rest * 0x10000) + ud0)) {
   4.400 +                --qest;
   4.401 +                rest += vd1;
   4.402 +            }
   4.403 +
   4.404 +            // 0 <= (qest - qj) <= 1
   4.405 +            
   4.406 +            // Multiply and subtract
   4.407 +            var carry = 0;
   4.408 +            for (var i = 0; i < n; ++i) {
   4.409 +                var vi = qest * v.getDigit(i, nrm);
   4.410 +                var ui = r.getDigit(i + j, nrm) - carry - (vi & 0xffff);
   4.411 +                r.setDigit(i + j, nrm, ui);
   4.412 +                carry = (vi >>> 16) - (ui >> 16);
   4.413 +            }
   4.414 +            var uj = ud2 - carry;
   4.415 +
   4.416 +            if (uj < 0) {
   4.417 +                // qest - qj = 1
   4.418 +
   4.419 +                // Add back
   4.420 +                --qest;
   4.421 +                var carry = 0;
   4.422 +                for (var i = 0; i < n; ++i) {
   4.423 +                    var ui = r.getDigit(i + j, nrm) + v.getDigit(i, nrm)
   4.424 +                                 + carry;
   4.425 +                    r.setDigit(i + j, nrm, ui);
   4.426 +                    carry = ui >> 16;
   4.427 +                }
   4.428 +                uj += carry;
   4.429 +            }
   4.430 +
   4.431 +            q.setDigit(j, 0, qest);
   4.432 +            r.setDigit(j + n, nrm, uj);
   4.433 +        }
   4.434 +    }
   4.435 +    
   4.436 +    numberPrototype.div64 = function(x) {
   4.437 +        var negateResult = false;
   4.438 +        var u, v;
   4.439 +        
   4.440 +        if ((this.high32() & 0x80000000) != 0) {
   4.441 +            u = this.neg64();
   4.442 +            negateResult = !negateResult;
   4.443 +        } else {
   4.444 +            u = this;        
   4.445 +        }
   4.446 +
   4.447 +        if ((x.high32() & 0x80000000) != 0) {
   4.448 +            v = x.neg64();
   4.449 +            negateResult = !negateResult;
   4.450 +        } else {
   4.451 +            v = x;
   4.452 +        }
   4.453 +
   4.454 +        if ((v === 0) && (v.high32() === 0)) {
   4.455 +            // TODO: throw
   4.456 +        }
   4.457 +
   4.458 +        if (u.high32() === 0) {
   4.459 +            if (v.high32() === 0) {
   4.460 +                var result = (u / v) | 0;
   4.461 +                return negateResult ? result.neg64() : result; 
   4.462 +            }
   4.463 +
   4.464 +            return 0;
   4.465 +        }
   4.466 +
   4.467 +        var u64 = new __Int64(u.high32(), u);
   4.468 +        var v64 = new __Int64(v.high32(), v);
   4.469 +        var q64 = new __Int64(0, 0);
   4.470 +        var r64 = new __Int64(0, 0);
   4.471 +
   4.472 +        __div64(q64, r64, u64, v64);
   4.473 +
   4.474 +        var result = q64.toNumber();
   4.475 +        return negateResult ? result.neg64() : result; 
   4.476 +    }
   4.477 +
   4.478 +    numberPrototype.mod64 = function(x) {
   4.479 +        var negateResult = false;
   4.480 +        var u, v;
   4.481 +        
   4.482 +        if ((this.high32() & 0x80000000) != 0) {
   4.483 +            u = this.neg64();
   4.484 +            negateResult = !negateResult;
   4.485 +        } else {
   4.486 +            u = this;        
   4.487 +        }
   4.488 +
   4.489 +        if ((x.high32() & 0x80000000) != 0) {
   4.490 +            v = x.neg64();
   4.491 +        } else {
   4.492 +            v = x;
   4.493 +        }
   4.494 +
   4.495 +        if ((v === 0) && (v.high32() === 0)) {
   4.496 +            // TODO: throw
   4.497 +        }
   4.498 +
   4.499 +        if (u.high32() === 0) {
   4.500 +            var result = (v.high32() === 0) ? (u % v) : u;
   4.501 +            return negateResult ? result.neg64() : result; 
   4.502 +        }
   4.503 +
   4.504 +        var u64 = new __Int64(u.high32(), u);
   4.505 +        var v64 = new __Int64(v.high32(), v);
   4.506 +        var q64 = new __Int64(0, 0);
   4.507 +        var r64 = new __Int64(0, 0);
   4.508 +
   4.509 +        __div64(q64, r64, u64, v64);
   4.510 +
   4.511 +        var result = r64.toNumber();
   4.512 +        return negateResult ? result.neg64() : result; 
   4.513 +    }
   4.514 +})(Number.prototype);
     5.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Thu Feb 07 12:58:12 2013 +0100
     5.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Thu Feb 07 13:07:22 2013 +0100
     5.3 @@ -521,7 +521,7 @@
     5.4                      emit(out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI());
     5.5                      break;
     5.6                  case opc_ladd:
     5.7 -                    emit(out, "@1 += @2;", smapper.getL(1), smapper.popL());
     5.8 +                    emit(out, "@1 = @1.add64(@2);", smapper.getL(1), smapper.popL());
     5.9                      break;
    5.10                  case opc_fadd:
    5.11                      emit(out, "@1 += @2;", smapper.getF(1), smapper.popF());
    5.12 @@ -533,7 +533,7 @@
    5.13                      emit(out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI());
    5.14                      break;
    5.15                  case opc_lsub:
    5.16 -                    emit(out, "@1 -= @2;", smapper.getL(1), smapper.popL());
    5.17 +                    emit(out, "@1 = @1.sub64(@2);", smapper.getL(1), smapper.popL());
    5.18                      break;
    5.19                  case opc_fsub:
    5.20                      emit(out, "@1 -= @2;", smapper.getF(1), smapper.popF());
    5.21 @@ -545,7 +545,7 @@
    5.22                      emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI());
    5.23                      break;
    5.24                  case opc_lmul:
    5.25 -                    emit(out, "@1 *= @2;", smapper.getL(1), smapper.popL());
    5.26 +                    emit(out, "@1 = @1.mul64(@2);", smapper.getL(1), smapper.popL());
    5.27                      break;
    5.28                  case opc_fmul:
    5.29                      emit(out, "@1 *= @2;", smapper.getF(1), smapper.popF());
    5.30 @@ -558,7 +558,7 @@
    5.31                           smapper.getI(1), smapper.popI());
    5.32                      break;
    5.33                  case opc_ldiv:
    5.34 -                    emit(out, "@1 = Math.floor(@1 / @2);",
    5.35 +                    emit(out, "@1 = @1.div64(@2);",
    5.36                           smapper.getL(1), smapper.popL());
    5.37                      break;
    5.38                  case opc_fdiv:
    5.39 @@ -571,7 +571,8 @@
    5.40                      emit(out, "@1 %= @2;", smapper.getI(1), smapper.popI());
    5.41                      break;
    5.42                  case opc_lrem:
    5.43 -                    emit(out, "@1 %= @2;", smapper.getL(1), smapper.popL());
    5.44 +                    emit(out, "@1 = @1.mod64(@2);",
    5.45 +                         smapper.getL(1), smapper.popL());
    5.46                      break;
    5.47                  case opc_frem:
    5.48                      emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF());
    5.49 @@ -583,25 +584,25 @@
    5.50                      emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI());
    5.51                      break;
    5.52                  case opc_land:
    5.53 -                    emit(out, "@1 &= @2;", smapper.getL(1), smapper.popL());
    5.54 +                    emit(out, "@1 = @1.and64(@2);", smapper.getL(1), smapper.popL());
    5.55                      break;
    5.56                  case opc_ior:
    5.57                      emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI());
    5.58                      break;
    5.59                  case opc_lor:
    5.60 -                    emit(out, "@1 |= @2;", smapper.getL(1), smapper.popL());
    5.61 +                    emit(out, "@1 = @1.or64(@2);", smapper.getL(1), smapper.popL());
    5.62                      break;
    5.63                  case opc_ixor:
    5.64                      emit(out, "@1 ^= @2;", smapper.getI(1), smapper.popI());
    5.65                      break;
    5.66                  case opc_lxor:
    5.67 -                    emit(out, "@1 ^= @2;", smapper.getL(1), smapper.popL());
    5.68 +                    emit(out, "@1 = @1.xor64(@2);", smapper.getL(1), smapper.popL());
    5.69                      break;
    5.70                  case opc_ineg:
    5.71                      emit(out, "@1 = -@1;", smapper.getI(0));
    5.72                      break;
    5.73                  case opc_lneg:
    5.74 -                    emit(out, "@1 = -@1;", smapper.getL(0));
    5.75 +                    emit(out, "@1 = @1.neg64();", smapper.getL(0));
    5.76                      break;
    5.77                  case opc_fneg:
    5.78                      emit(out, "@1 = -@1;", smapper.getF(0));
    5.79 @@ -613,19 +614,19 @@
    5.80                      emit(out, "@1 <<= @2;", smapper.getI(1), smapper.popI());
    5.81                      break;
    5.82                  case opc_lshl:
    5.83 -                    emit(out, "@1 <<= @2;", smapper.getL(1), smapper.popI());
    5.84 +                    emit(out, "@1 = @1.shl64(@2);", smapper.getL(1), smapper.popI());
    5.85                      break;
    5.86                  case opc_ishr:
    5.87                      emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI());
    5.88                      break;
    5.89                  case opc_lshr:
    5.90 -                    emit(out, "@1 >>= @2;", smapper.getL(1), smapper.popI());
    5.91 +                    emit(out, "@1 = @1.shr64(@2);", smapper.getL(1), smapper.popI());
    5.92                      break;
    5.93                  case opc_iushr:
    5.94                      emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI());
    5.95                      break;
    5.96                  case opc_lushr:
    5.97 -                    emit(out, "@1 >>>= @2;", smapper.getL(1), smapper.popI());
    5.98 +                    emit(out, "@1 = @1.ushr64(@2);", smapper.getL(1), smapper.popI());
    5.99                      break;
   5.100                  case opc_iinc: {
   5.101                      ++i;
   5.102 @@ -672,14 +673,14 @@
   5.103                      emit(out, "var @2 = @1;", smapper.popI(), smapper.pushD());
   5.104                      break;
   5.105                  case opc_l2i:
   5.106 -                    emit(out, "var @2 = @1;", smapper.popL(), smapper.pushI());
   5.107 +                    emit(out, "var @2 = @1.toInt32();", smapper.popL(), smapper.pushI());
   5.108                      break;
   5.109                      // max int check?
   5.110                  case opc_l2f:
   5.111 -                    emit(out, "var @2 = @1;", smapper.popL(), smapper.pushF());
   5.112 +                    emit(out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushF());
   5.113                      break;
   5.114                  case opc_l2d:
   5.115 -                    emit(out, "var @2 = @1;", smapper.popL(), smapper.pushD());
   5.116 +                    emit(out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushD());
   5.117                      break;
   5.118                  case opc_f2d:
   5.119                      emit(out, "var @2 = @1;", smapper.popF(), smapper.pushD());
   5.120 @@ -692,7 +693,7 @@
   5.121                           smapper.popF(), smapper.pushI());
   5.122                      break;
   5.123                  case opc_f2l:
   5.124 -                    emit(out, "var @2 = Math.floor(@1);",
   5.125 +                    emit(out, "var @2 = Math.floor(@1).toLong();",
   5.126                           smapper.popF(), smapper.pushL());
   5.127                      break;
   5.128                  case opc_d2i:
   5.129 @@ -700,7 +701,7 @@
   5.130                           smapper.popD(), smapper.pushI());
   5.131                      break;
   5.132                  case opc_d2l:
   5.133 -                    emit(out, "var @2 = Math.floor(@1);",
   5.134 +                    emit(out, "var @2 = Math.floor(@1).toLong();",
   5.135                           smapper.popD(), smapper.pushL());
   5.136                      break;
   5.137                  case opc_i2b:
   5.138 @@ -770,11 +771,19 @@
   5.139                      i += 2;
   5.140                      String v = encodeConstant(indx);
   5.141                      int type = VarType.fromConstantType(jc.getTag(indx));
   5.142 -                    emit(out, "var @1 = @2;", smapper.pushT(type), v);
   5.143 +                    if (type == VarType.LONG) {
   5.144 +                        final Long lv = new Long(v);
   5.145 +                        final int low = (int)(lv.longValue() & 0xFFFFFFFF);
   5.146 +                        final int hi = (int)(lv.longValue() >> 32);
   5.147 +                        emit(out, "var @1 = 0x@3.next32(0x@2);", smapper.pushL(), 
   5.148 +                                Integer.toHexString(low), Integer.toHexString(hi));
   5.149 +                    } else {
   5.150 +                        emit(out, "var @1 = @2;", smapper.pushT(type), v);
   5.151 +                    }
   5.152                      break;
   5.153                  }
   5.154                  case opc_lcmp:
   5.155 -                    emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
   5.156 +                    emit(out, "var @3 = @2.compare64(@1);",
   5.157                           smapper.popL(), smapper.popL(), smapper.pushI());
   5.158                      break;
   5.159                  case opc_fcmpl:
     6.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Thu Feb 07 12:58:12 2013 +0100
     6.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Thu Feb 07 13:07:22 2013 +0100
     6.3 @@ -144,6 +144,552 @@
     6.4          );
     6.5      }
     6.6      
     6.7 +    @Test public void longConversion() throws Exception {
     6.8 +        assertExec("Long from cPool",
     6.9 +            Numbers.class, "conversionL__J", 
    6.10 +            Double.valueOf(Long.MAX_VALUE)
    6.11 +        );
    6.12 +    }
    6.13 +    
    6.14 +    @Test public void longNegate1() throws Exception {
    6.15 +        final long res = -0x00fa37d7763e0ca1l;
    6.16 +        assertExec("Long negate",
    6.17 +            Numbers.class, "negL__J_3B", 
    6.18 +            Double.valueOf(res),
    6.19 +                new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 }
    6.20 +        );
    6.21 +    }
    6.22 +    
    6.23 +    @Test public void longNegate2() throws Exception {
    6.24 +        final long res = -0x80fa37d7763e0ca1l;
    6.25 +        assertExec("Long negate",
    6.26 +            Numbers.class, "negL__J_3B", 
    6.27 +            Double.valueOf(res),
    6.28 +                new byte[] { (byte)0x80, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 }
    6.29 +        );
    6.30 +    }
    6.31 +
    6.32 +    @Test public void longNegate3() throws Exception {
    6.33 +        final long res = -0xfffffffffffffeddl;
    6.34 +        assertExec("Long negate",
    6.35 +            Numbers.class, "negL__J_3B",
    6.36 +            Double.valueOf(res),
    6.37 +                new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd }
    6.38 +        );
    6.39 +    }
    6.40 +
    6.41 +    @Test public void longAddOverflow() throws Exception {
    6.42 +        final long res = Long.MAX_VALUE + 1l;
    6.43 +        assertExec("Addition 1+MAX",
    6.44 +            Numbers.class, "addL__J_3B_3B", 
    6.45 +            Double.valueOf(res),
    6.46 +                new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff },
    6.47 +                new byte[] { (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)1 }
    6.48 +        );
    6.49 +    }
    6.50 +    
    6.51 +    @Test public void longAddMaxAndMax() throws Exception {
    6.52 +        final long res = Long.MAX_VALUE + Long.MAX_VALUE;
    6.53 +        assertExec("Addition MAX+MAX",
    6.54 +            Numbers.class, "addL__J_3B_3B", 
    6.55 +            Double.valueOf(res),
    6.56 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff },
    6.57 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }
    6.58 +        );
    6.59 +    }
    6.60 +    
    6.61 +    @Test public void longSubUnderflow() throws Exception {
    6.62 +        final long res = Long.MIN_VALUE - 1l;
    6.63 +        assertExec("Subtraction MIN-1",
    6.64 +            Numbers.class, "subL__J_3B_3B", 
    6.65 +            Double.valueOf(res),
    6.66 +                new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
    6.67 +                new byte[] { (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)1 }
    6.68 +        );
    6.69 +    }
    6.70 +    
    6.71 +    @Test public void longSubMinAndMin() throws Exception {
    6.72 +        final long res = Long.MIN_VALUE - Long.MIN_VALUE;
    6.73 +        assertExec("Subtraction MIN-MIN",
    6.74 +            Numbers.class, "subL__J_3B_3B", 
    6.75 +            Double.valueOf(res),
    6.76 +            new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
    6.77 +            new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }
    6.78 +        );
    6.79 +    }
    6.80 +    
    6.81 +    @Test public void longSubMinAndMax() throws Exception {
    6.82 +        final long res = Long.MIN_VALUE - Long.MAX_VALUE;
    6.83 +        assertExec("Subtraction MIN-MAX",
    6.84 +            Numbers.class, "subL__J_3B_3B", 
    6.85 +            Double.valueOf(res),
    6.86 +            new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
    6.87 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }
    6.88 +        );
    6.89 +    }
    6.90 +    
    6.91 +    @Test public void longMultiplyMax() throws Exception {
    6.92 +        final long res = Long.MAX_VALUE * 2l;
    6.93 +        assertExec("Multiplication MAX*2",
    6.94 +            Numbers.class, "mulL__J_3B_3B",
    6.95 +            Double.valueOf(res),
    6.96 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff },
    6.97 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02 }
    6.98 +        );
    6.99 +    }
   6.100 +    
   6.101 +    @Test public void longMultiplyMaxAndMax() throws Exception {
   6.102 +        final long res = Long.MAX_VALUE * Long.MAX_VALUE;
   6.103 +        assertExec("Multiplication MAX*MAX",
   6.104 +            Numbers.class, "mulL__J_3B_3B",
   6.105 +            Double.valueOf(res),
   6.106 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff },
   6.107 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }
   6.108 +        );
   6.109 +    }
   6.110 +    
   6.111 +    @Test public void longMultiplyMin() throws Exception {
   6.112 +        final long res = Long.MIN_VALUE * 2l;
   6.113 +        assertExec("Multiplication MIN*2",
   6.114 +            Numbers.class, "mulL__J_3B_3B",
   6.115 +            Double.valueOf(res),
   6.116 +            new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
   6.117 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02 }
   6.118 +        );
   6.119 +    }
   6.120 +    
   6.121 +    @Test public void longMultiplyMinAndMin() throws Exception {
   6.122 +        final long res = Long.MIN_VALUE * Long.MIN_VALUE;
   6.123 +        assertExec("Multiplication MIN*2",
   6.124 +            Numbers.class, "mulL__J_3B_3B",
   6.125 +            Double.valueOf(res),
   6.126 +            new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
   6.127 +            new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }
   6.128 +        );
   6.129 +    }
   6.130 +    
   6.131 +    @Test public void longMultiplyPrecision() throws Exception {
   6.132 +        final long res = 0x00fa37d7763e0ca1l * 0xa7b3432fff00123el;
   6.133 +        assertExec("Multiplication",
   6.134 +            Numbers.class, "mulL__J_3B_3B",
   6.135 +            Double.valueOf(res),
   6.136 +            new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.137 +            new byte[] { (byte)0xa7, (byte)0xb3, (byte)0x43, (byte)0x2f, (byte)0xff, (byte)0x00, (byte)0x12, (byte)0x3e }
   6.138 +        );
   6.139 +    }
   6.140 +
   6.141 +    @Test public void longDivideSmallPositiveNumbers() throws Exception {
   6.142 +        final long res = 0xabcdef / 0x123;
   6.143 +        assertExec("Division Small Positive Numbers",
   6.144 +            Numbers.class, "divL__J_3B_3B",
   6.145 +            Double.valueOf(res),
   6.146 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef },
   6.147 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x23 }
   6.148 +        );
   6.149 +    }
   6.150 +
   6.151 +    @Test public void longDivideSmallNegativeNumbers() throws Exception {
   6.152 +        final long res = -0xabcdef / -0x123;
   6.153 +        assertExec("Division Small Negative Numbers",
   6.154 +            Numbers.class, "divL__J_3B_3B",
   6.155 +            Double.valueOf(res),
   6.156 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x11 },
   6.157 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd }
   6.158 +        );
   6.159 +    }
   6.160 +
   6.161 +    @Test public void longDivideSmallMixedNumbers() throws Exception {
   6.162 +        final long res = 0xabcdef / -0x123;
   6.163 +        assertExec("Division Small Mixed Numbers",
   6.164 +            Numbers.class, "divL__J_3B_3B",
   6.165 +            Double.valueOf(res),
   6.166 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef },
   6.167 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd }
   6.168 +        );
   6.169 +    }
   6.170 +
   6.171 +    @Test public void longDividePositiveNumbersOneDigitDenom()
   6.172 +            throws Exception {
   6.173 +        final long res = 0xabcdef0102ffffL / 0x654;
   6.174 +        assertExec("Division Positive Numbers One Digit Denom",
   6.175 +            Numbers.class, "divL__J_3B_3B",
   6.176 +            Double.valueOf(res),
   6.177 +            new byte[] { (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef, (byte)0x01, (byte)0x02, (byte)0xff, (byte)0xff },
   6.178 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 }
   6.179 +        );
   6.180 +    }
   6.181 +
   6.182 +    @Test public void longDivideNegativeNumbersOneDigitDenom()
   6.183 +            throws Exception {
   6.184 +        final long res = -0xabcdef0102ffffL / -0x654;
   6.185 +        assertExec("Division Negative Numbers One Digit Denom",
   6.186 +            Numbers.class, "divL__J_3B_3B",
   6.187 +            Double.valueOf(res),
   6.188 +            new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 },
   6.189 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf9, (byte)0xac }
   6.190 +        );
   6.191 +    }
   6.192 +
   6.193 +    @Test public void longDivideMixedNumbersOneDigitDenom()
   6.194 +            throws Exception {
   6.195 +        final long res = -0xabcdef0102ffffL / 0x654;
   6.196 +        assertExec("Division Mixed Numbers One Digit Denom",
   6.197 +            Numbers.class, "divL__J_3B_3B",
   6.198 +            Double.valueOf(res),
   6.199 +            new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 },
   6.200 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 }
   6.201 +        );
   6.202 +    }
   6.203 +
   6.204 +    @Test public void longDividePositiveNumbersMultiDigitDenom()
   6.205 +            throws Exception {
   6.206 +        final long res = 0x7ffefc003322aabbL / 0x89ab1000L;
   6.207 +        assertExec("Division Positive Numbers Multi Digit Denom",
   6.208 +            Numbers.class, "divL__J_3B_3B",
   6.209 +            Double.valueOf(res),
   6.210 +            new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb },
   6.211 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x89, (byte)0xab, (byte)0x10, (byte)0x00 }
   6.212 +        );
   6.213 +    }
   6.214 +
   6.215 +    @Test public void longDivideNegativeNumbersMultiDigitDenom()
   6.216 +            throws Exception {
   6.217 +        final long res = -0x7ffefc003322aabbL / -0x123489ab1001L;
   6.218 +        assertExec("Division Negative Numbers Multi Digit Denom",
   6.219 +            Numbers.class, "divL__J_3B_3B",
   6.220 +            Double.valueOf(res),
   6.221 +            new byte[] { (byte)0x80, (byte)0x01, (byte)0x03, (byte)0xff, (byte)0xcc, (byte)0xdd, (byte)0x55, (byte)0x45 },
   6.222 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xed, (byte)0xcb, (byte)0x76, (byte)0x54, (byte)0xef, (byte)0xff }
   6.223 +        );
   6.224 +    }
   6.225 +
   6.226 +    @Test public void longDivideMixedNumbersMultiDigitDenom()
   6.227 +            throws Exception {
   6.228 +        final long res = 0x7ffefc003322aabbL / -0x38f49b0b7574e36L;
   6.229 +        assertExec("Division Mixed Numbers Multi Digit Denom",
   6.230 +            Numbers.class, "divL__J_3B_3B",
   6.231 +            Double.valueOf(res),
   6.232 +            new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb },
   6.233 +            new byte[] { (byte)0xfc, (byte)0x70, (byte)0xb6, (byte)0x4f, (byte)0x48, (byte)0xa8, (byte)0xb1, (byte)0xca }
   6.234 +        );
   6.235 +    }
   6.236 +
   6.237 +    @Test public void longDivideWithOverflow() throws Exception {
   6.238 +        final long res = 0x8000fffe0000L / 0x8000ffffL;
   6.239 +        assertExec("Division With Overflow",
   6.240 +            Numbers.class, "divL__J_3B_3B",
   6.241 +            Double.valueOf(res),
   6.242 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xfe, (byte)0x00, (byte)0x00 },
   6.243 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xff }
   6.244 +        );
   6.245 +    }
   6.246 +
   6.247 +    @Test public void longDivideWithCorrection() throws Exception {
   6.248 +        final long res = 0x7fff800000000000L / 0x800000000001L;
   6.249 +        assertExec("Division With Correction",
   6.250 +            Numbers.class, "divL__J_3B_3B",
   6.251 +            Double.valueOf(res),
   6.252 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
   6.253 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01 }
   6.254 +        );
   6.255 +    }
   6.256 +
   6.257 +    @Test public void longModuloSmallPositiveNumbers() throws Exception {
   6.258 +        final long res = 0xabcdef % 0x123;
   6.259 +        assertExec("Modulo Small Positive Numbers",
   6.260 +            Numbers.class, "modL__J_3B_3B",
   6.261 +            Double.valueOf(res),
   6.262 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef },
   6.263 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x23 }
   6.264 +        );
   6.265 +    }
   6.266 +
   6.267 +    @Test public void longModuloSmallNegativeNumbers() throws Exception {
   6.268 +        final long res = -0xabcdef % -0x123;
   6.269 +        assertExec("Modulo Small Negative Numbers",
   6.270 +            Numbers.class, "modL__J_3B_3B",
   6.271 +            Double.valueOf(res),
   6.272 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x11 },
   6.273 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd }
   6.274 +        );
   6.275 +    }
   6.276 +
   6.277 +    @Test public void longModuloSmallMixedNumbers() throws Exception {
   6.278 +        final long res = 0xabcdef % -0x123;
   6.279 +        assertExec("Modulo Small Mixed Numbers",
   6.280 +            Numbers.class, "modL__J_3B_3B",
   6.281 +            Double.valueOf(res),
   6.282 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef },
   6.283 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd }
   6.284 +        );
   6.285 +    }
   6.286 +
   6.287 +    @Test public void longModuloPositiveNumbersOneDigitDenom()
   6.288 +            throws Exception {
   6.289 +        final long res = 0xabcdef0102ffffL % 0x654;
   6.290 +        assertExec("Modulo Positive Numbers One Digit Denom",
   6.291 +            Numbers.class, "modL__J_3B_3B",
   6.292 +            Double.valueOf(res),
   6.293 +            new byte[] { (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef, (byte)0x01, (byte)0x02, (byte)0xff, (byte)0xff },
   6.294 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 }
   6.295 +        );
   6.296 +    }
   6.297 +
   6.298 +    @Test public void longModuloNegativeNumbersOneDigitDenom()
   6.299 +            throws Exception {
   6.300 +        final long res = -0xabcdef0102ffffL % -0x654;
   6.301 +        assertExec("Modulo Negative Numbers One Digit Denom",
   6.302 +            Numbers.class, "modL__J_3B_3B",
   6.303 +            Double.valueOf(res),
   6.304 +            new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 },
   6.305 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf9, (byte)0xac }
   6.306 +        );
   6.307 +    }
   6.308 +
   6.309 +    @Test public void longModuloMixedNumbersOneDigitDenom()
   6.310 +            throws Exception {
   6.311 +        final long res = -0xabcdef0102ffffL % 0x654;
   6.312 +        assertExec("Modulo Mixed Numbers One Digit Denom",
   6.313 +            Numbers.class, "modL__J_3B_3B",
   6.314 +            Double.valueOf(res),
   6.315 +            new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 },
   6.316 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 }
   6.317 +        );
   6.318 +    }
   6.319 +
   6.320 +    @Test public void longModuloPositiveNumbersMultiDigitDenom()
   6.321 +            throws Exception {
   6.322 +        final long res = 0x7ffefc003322aabbL % 0x89ab1000L;
   6.323 +        assertExec("Modulo Positive Numbers Multi Digit Denom",
   6.324 +            Numbers.class, "modL__J_3B_3B",
   6.325 +            Double.valueOf(res),
   6.326 +            new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb },
   6.327 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x89, (byte)0xab, (byte)0x10, (byte)0x00 }
   6.328 +        );
   6.329 +    }
   6.330 +
   6.331 +    @Test public void longModuloNegativeNumbersMultiDigitDenom()
   6.332 +            throws Exception {
   6.333 +        final long res = -0x7ffefc003322aabbL % -0x123489ab1001L;
   6.334 +        assertExec("Modulo Negative Numbers Multi Digit Denom",
   6.335 +            Numbers.class, "modL__J_3B_3B",
   6.336 +            Double.valueOf(res),
   6.337 +            new byte[] { (byte)0x80, (byte)0x01, (byte)0x03, (byte)0xff, (byte)0xcc, (byte)0xdd, (byte)0x55, (byte)0x45 },
   6.338 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xed, (byte)0xcb, (byte)0x76, (byte)0x54, (byte)0xef, (byte)0xff }
   6.339 +        );
   6.340 +    }
   6.341 +
   6.342 +    @Test public void longModuloMixedNumbersMultiDigitDenom()
   6.343 +            throws Exception {
   6.344 +        final long res = 0x7ffefc003322aabbL % -0x38f49b0b7574e36L;
   6.345 +        assertExec("Modulo Mixed Numbers Multi Digit Denom",
   6.346 +            Numbers.class, "modL__J_3B_3B",
   6.347 +            Double.valueOf(res),
   6.348 +            new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb },
   6.349 +            new byte[] { (byte)0xfc, (byte)0x70, (byte)0xb6, (byte)0x4f, (byte)0x48, (byte)0xa8, (byte)0xb1, (byte)0xca }
   6.350 +        );
   6.351 +    }
   6.352 +
   6.353 +    @Test public void longModuloWithOverflow() throws Exception {
   6.354 +        final long res = 0x8000fffe0000L % 0x8000ffffL;
   6.355 +        assertExec("Modulo With Overflow",
   6.356 +            Numbers.class, "modL__J_3B_3B",
   6.357 +            Double.valueOf(res),
   6.358 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xfe, (byte)0x00, (byte)0x00 },
   6.359 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xff }
   6.360 +        );
   6.361 +    }
   6.362 +
   6.363 +    @Test public void longModuloWithCorrection() throws Exception {
   6.364 +        final long res = 0x7fff800000000000L % 0x800000000001L;
   6.365 +        assertExec("Modulo With Correction",
   6.366 +            Numbers.class, "modL__J_3B_3B",
   6.367 +            Double.valueOf(res),
   6.368 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
   6.369 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01 }
   6.370 +        );
   6.371 +    }
   6.372 +
   6.373 +    @Test public void longShiftL1() throws Exception {
   6.374 +        final long res = 0x00fa37d7763e0ca1l << 5;
   6.375 +        assertExec("Long << 5",
   6.376 +            Numbers.class, "shlL__J_3BI", 
   6.377 +            Double.valueOf(res),
   6.378 +                new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.379 +                5);
   6.380 +    }
   6.381 +    
   6.382 +    @Test public void longShiftL2() throws Exception {
   6.383 +        final long res = 0x00fa37d7763e0ca1l << 32;
   6.384 +        assertExec("Long << 32",
   6.385 +            Numbers.class, "shlL__J_3BI", 
   6.386 +            Double.valueOf(res),
   6.387 +                new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.388 +                32);
   6.389 +    }
   6.390 +    
   6.391 +    @Test public void longShiftL3() throws Exception {
   6.392 +        final long res = 0x00fa37d7763e0ca1l << 45;
   6.393 +        assertExec("Long << 45",
   6.394 +            Numbers.class, "shlL__J_3BI", 
   6.395 +            Double.valueOf(res),
   6.396 +                new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.397 +                45);
   6.398 +    }
   6.399 +    
   6.400 +    @Test public void longShiftR1() throws Exception {
   6.401 +        final long res = 0x00fa37d7763e0ca1l >> 5;
   6.402 +        assertExec("Long >> 5",
   6.403 +            Numbers.class, "shrL__J_3BI", 
   6.404 +            Double.valueOf(res),
   6.405 +                new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.406 +                5);
   6.407 +    }
   6.408 +    
   6.409 +    @Test public void longShiftR2() throws Exception {
   6.410 +        final long res = 0x00fa37d7763e0ca1l >> 32;
   6.411 +        assertExec("Long >> 32",
   6.412 +            Numbers.class, "shrL__J_3BI", 
   6.413 +            Double.valueOf(res),
   6.414 +                new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.415 +                32);
   6.416 +    }
   6.417 +    
   6.418 +    @Test public void longShiftR3() throws Exception {
   6.419 +        final long res = 0x00fa37d7763e0ca1l >> 45;
   6.420 +        assertExec("Long >> 45",
   6.421 +            Numbers.class, "shrL__J_3BI", 
   6.422 +            Double.valueOf(res),
   6.423 +                new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.424 +                45);
   6.425 +    }
   6.426 +    
   6.427 +    @Test public void longUShiftR1() throws Exception {
   6.428 +        final long res = 0x00fa37d7763e0ca1l >>> 5;
   6.429 +        assertExec("Long >>> 5",
   6.430 +            Numbers.class, "ushrL__J_3BI", 
   6.431 +            Double.valueOf(res),
   6.432 +                new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.433 +                5);
   6.434 +    }
   6.435 +    
   6.436 +    @Test public void longUShiftR2() throws Exception {
   6.437 +        final long res = 0x00fa37d7763e0ca1l >>> 45;
   6.438 +        assertExec("Long >>> 45",
   6.439 +            Numbers.class, "ushrL__J_3BI", 
   6.440 +            Double.valueOf(res),
   6.441 +                new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.442 +                45);
   6.443 +    }
   6.444 +    
   6.445 +    @Test public void longUShiftR3() throws Exception {
   6.446 +        final long res = 0xf0fa37d7763e0ca1l >>> 5;
   6.447 +        assertExec("Long >>> 5",
   6.448 +            Numbers.class, "ushrL__J_3BI", 
   6.449 +            Double.valueOf(res),
   6.450 +                new byte[] { (byte)0xf0, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.451 +                5);
   6.452 +    }
   6.453 +    
   6.454 +    @Test public void longUShiftR4() throws Exception {
   6.455 +        final long res = 0xf0fa37d7763e0ca1l >>> 45;
   6.456 +        assertExec("Long >>> 45",
   6.457 +            Numbers.class, "ushrL__J_3BI", 
   6.458 +            Double.valueOf(res),
   6.459 +                new byte[] { (byte)0xf0, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.460 +                45);
   6.461 +    }
   6.462 +    
   6.463 +    @Test public void longAnd() throws Exception {
   6.464 +        final long res = 0x00fa37d7763e0ca1l & 0xa7b3432fff00123el;
   6.465 +        assertExec("LOng binary AND",
   6.466 +            Numbers.class, "andL__J_3B_3B", 
   6.467 +            Double.valueOf(res),
   6.468 +            new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.469 +            new byte[] { (byte)0xa7, (byte)0xb3, (byte)0x43, (byte)0x2f, (byte)0xff, (byte)0x00, (byte)0x12, (byte)0x3e }
   6.470 +        );
   6.471 +    }
   6.472 +    
   6.473 +    @Test public void longOr() throws Exception {
   6.474 +        final long res = 0x00fa37d7763e0ca1l | 0xa7b3432fff00123el;
   6.475 +        assertExec("Long binary OR",
   6.476 +            Numbers.class, "orL__J_3B_3B", 
   6.477 +            Double.valueOf(res),
   6.478 +            new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.479 +            new byte[] { (byte)0xa7, (byte)0xb3, (byte)0x43, (byte)0x2f, (byte)0xff, (byte)0x00, (byte)0x12, (byte)0x3e }
   6.480 +        );
   6.481 +    }
   6.482 +    
   6.483 +    @Test public void longXor1() throws Exception {
   6.484 +        final long res = 0x00fa37d7763e0ca1l ^ 0xa7b3432fff00123el;
   6.485 +        assertExec("Long binary XOR",
   6.486 +            Numbers.class, "xorL__J_3B_3B", 
   6.487 +            Double.valueOf(res),
   6.488 +            new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.489 +            new byte[] { (byte)0xa7, (byte)0xb3, (byte)0x43, (byte)0x2f, (byte)0xff, (byte)0x00, (byte)0x12, (byte)0x3e }
   6.490 +        );
   6.491 +    }
   6.492 +    
   6.493 +    @Test public void longXor2() throws Exception {
   6.494 +        final long res = 0x00fa37d7763e0ca1l ^ 0x00000000ff00123el;
   6.495 +        assertExec("Long binary XOR",
   6.496 +            Numbers.class, "xorL__J_3B_3B", 
   6.497 +            Double.valueOf(res),
   6.498 +            new byte[] { (byte)0x00, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.499 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xff, (byte)0x00, (byte)0x12, (byte)0x3e }
   6.500 +        );
   6.501 +    }
   6.502 +    
   6.503 +    @Test public void longXor3() throws Exception {
   6.504 +        final long res = 0x00000000763e0ca1l ^ 0x00000000ff00123el;
   6.505 +        assertExec("Long binary XOR",
   6.506 +            Numbers.class, "xorL__J_3B_3B", 
   6.507 +            Double.valueOf(res),
   6.508 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 },
   6.509 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xff, (byte)0x00, (byte)0x12, (byte)0x3e }
   6.510 +        );
   6.511 +    }
   6.512 +
   6.513 +    @Test public void longCompareSameNumbers() throws Exception {
   6.514 +        assertExec("Long compare same numbers",
   6.515 +            Numbers.class, "compareL__I_3B_3BI",
   6.516 +            0.0,
   6.517 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
   6.518 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
   6.519 +            0
   6.520 +        );
   6.521 +    }
   6.522 +
   6.523 +    @Test public void longComparePositiveNumbers() throws Exception {
   6.524 +        assertExec("Long compare positive numbers",
   6.525 +            Numbers.class, "compareL__I_3B_3BI",
   6.526 +            -1.0,
   6.527 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x00 },
   6.528 +            new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00 },
   6.529 +            0
   6.530 +        );
   6.531 +    }
   6.532 +
   6.533 +    @Test public void longCompareNegativeNumbers() throws Exception {
   6.534 +        assertExec("Long compare negative numbers",
   6.535 +            Numbers.class, "compareL__I_3B_3BI",
   6.536 +            1.0,
   6.537 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff },
   6.538 +            new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
   6.539 +            0
   6.540 +        );
   6.541 +    }
   6.542 +
   6.543 +    @Test public void longCompareMixedNumbers() throws Exception {
   6.544 +        assertExec("Long compare mixed numbers",
   6.545 +            Numbers.class, "compareL__I_3B_3BI",
   6.546 +            -1.0,
   6.547 +            new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
   6.548 +            new byte[] { (byte)0x7f, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff },
   6.549 +            0
   6.550 +        );
   6.551 +    }
   6.552 +
   6.553      private static CharSequence codeSeq;
   6.554      private static Invocable code;
   6.555  
   6.556 @@ -157,31 +703,20 @@
   6.557      }
   6.558  
   6.559      private static void assertExec(
   6.560 -        String msg, Class<?> clazz, String method, Object expRes, Object... args) throws Exception {
   6.561 -
   6.562 -        Object ret = null;
   6.563 -        try {
   6.564 -            ret = code.invokeFunction("bck2brwsr");
   6.565 -            ret = code.invokeMethod(ret, "loadClass", clazz.getName());
   6.566 -            ret = code.invokeMethod(ret, method, args);
   6.567 -        } catch (ScriptException ex) {
   6.568 -            fail("Execution failed in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
   6.569 -        } catch (NoSuchMethodException ex) {
   6.570 -            fail("Cannot find method in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
   6.571 -        }
   6.572 -        if (ret == null && expRes == null) {
   6.573 -            return;
   6.574 -        }
   6.575 -        if (expRes.equals(ret)) {
   6.576 +        String msg, Class<?> clazz, String method, Object expRes, Object... args) throws Exception
   6.577 +    {
   6.578 +        Object ret = TestUtils.execCode(code, codeSeq, msg, clazz, method, expRes, args);
   6.579 +        if (ret == null) {
   6.580              return;
   6.581          }
   6.582          if (expRes instanceof Double && ret instanceof Double) {
   6.583              double expD = ((Double)expRes).doubleValue();
   6.584              double retD = ((Double)ret).doubleValue();
   6.585 -            assertEquals(retD, expD, 0.000004, msg + " was " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq));
   6.586 +            assertEquals(retD, expD, 0.000004, msg + " "
   6.587 +                    + StaticMethodTest.dumpJS(codeSeq));
   6.588              return;
   6.589          }
   6.590 -        assertEquals(ret, expRes, msg + "was: " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq));
   6.591 +        assertEquals(ret, expRes, msg + " " + StaticMethodTest.dumpJS(codeSeq));
   6.592      }
   6.593      
   6.594  }
     7.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java	Thu Feb 07 12:58:12 2013 +0100
     7.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java	Thu Feb 07 13:07:22 2013 +0100
     7.3 @@ -67,4 +67,136 @@
     7.4      static String floatToString() {
     7.5          return new Float(7.0).toString().toString();
     7.6      }
     7.7 +    
     7.8 +    public static long conversionL() {
     7.9 +        return Long.MAX_VALUE;
    7.10 +    }
    7.11 +    
    7.12 +    public static long negL(byte[] arrValue) throws IOException {
    7.13 +        ByteArrayInputStream isValue = new ByteArrayInputStream(arrValue);
    7.14 +        DataInputStream disValue = new DataInputStream(isValue);
    7.15 +        return (-disValue.readLong());
    7.16 +    }
    7.17 +    
    7.18 +    public static long addL(byte[] arrX, byte[] arrY) throws IOException {
    7.19 +        ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
    7.20 +        DataInputStream disX = new DataInputStream(isX);
    7.21 +        ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
    7.22 +        DataInputStream disY = new DataInputStream(isY);
    7.23 +        return (disX.readLong() + disY.readLong());
    7.24 +    }
    7.25 +    
    7.26 +    public static long subL(byte[] arrX, byte[] arrY) throws IOException {
    7.27 +        ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
    7.28 +        DataInputStream disX = new DataInputStream(isX);
    7.29 +        ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
    7.30 +        DataInputStream disY = new DataInputStream(isY);
    7.31 +        return (disX.readLong() - disY.readLong());
    7.32 +    }
    7.33 +    
    7.34 +    public static long mulL(byte[] arrX, byte[] arrY) throws IOException {
    7.35 +        ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
    7.36 +        DataInputStream disX = new DataInputStream(isX);
    7.37 +        ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
    7.38 +        DataInputStream disY = new DataInputStream(isY);
    7.39 +        return (disX.readLong() * disY.readLong());
    7.40 +    }
    7.41 +    
    7.42 +    public static long divL(byte[] arrX, byte[] arrY) throws IOException {
    7.43 +        ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
    7.44 +        DataInputStream disX = new DataInputStream(isX);
    7.45 +        ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
    7.46 +        DataInputStream disY = new DataInputStream(isY);
    7.47 +        return (disX.readLong() / disY.readLong());
    7.48 +    }
    7.49 +    
    7.50 +    public static long modL(byte[] arrX, byte[] arrY) throws IOException {
    7.51 +        ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
    7.52 +        DataInputStream disX = new DataInputStream(isX);
    7.53 +        ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
    7.54 +        DataInputStream disY = new DataInputStream(isY);
    7.55 +        return (disX.readLong() % disY.readLong());
    7.56 +    }
    7.57 +    
    7.58 +    public static long shlL(byte[] arrValue, int nBits) throws IOException {
    7.59 +        ByteArrayInputStream isValue = new ByteArrayInputStream(arrValue);
    7.60 +        DataInputStream disValue = new DataInputStream(isValue);
    7.61 +        return (disValue.readLong() << nBits);
    7.62 +    }
    7.63 +    
    7.64 +    public static long shrL(byte[] arrValue, int nBits) throws IOException {
    7.65 +        ByteArrayInputStream isValue = new ByteArrayInputStream(arrValue);
    7.66 +        DataInputStream disValue = new DataInputStream(isValue);
    7.67 +        return (disValue.readLong() >> nBits);
    7.68 +    }
    7.69 +    
    7.70 +    public static long ushrL(byte[] arrValue, int nBits) throws IOException {
    7.71 +        ByteArrayInputStream isValue = new ByteArrayInputStream(arrValue);
    7.72 +        DataInputStream disValue = new DataInputStream(isValue);
    7.73 +        return (disValue.readLong() >>> nBits);
    7.74 +    }
    7.75 +    
    7.76 +    public static long andL(byte[] arrX, byte[] arrY) throws IOException {
    7.77 +        ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
    7.78 +        DataInputStream disX = new DataInputStream(isX);
    7.79 +        ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
    7.80 +        DataInputStream disY = new DataInputStream(isY);
    7.81 +        return (disX.readLong() & disY.readLong());
    7.82 +    }
    7.83 +    
    7.84 +    public static long orL(byte[] arrX, byte[] arrY) throws IOException {
    7.85 +        ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
    7.86 +        DataInputStream disX = new DataInputStream(isX);
    7.87 +        ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
    7.88 +        DataInputStream disY = new DataInputStream(isY);
    7.89 +        return (disX.readLong() | disY.readLong());
    7.90 +    }
    7.91 +    
    7.92 +    public static long xorL(byte[] arrX, byte[] arrY) throws IOException {
    7.93 +        ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
    7.94 +        DataInputStream disX = new DataInputStream(isX);
    7.95 +        ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
    7.96 +        DataInputStream disY = new DataInputStream(isY);
    7.97 +        return (disX.readLong() ^ disY.readLong());
    7.98 +    }
    7.99 +
   7.100 +    public static int compareL(byte[] arrX, byte[] arrY,
   7.101 +                               int zero) throws IOException {
   7.102 +        ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
   7.103 +        DataInputStream disX = new DataInputStream(isX);
   7.104 +        ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
   7.105 +        DataInputStream disY = new DataInputStream(isY);
   7.106 +        final long x = disX.readLong();
   7.107 +        final long y = disY.readLong();
   7.108 +
   7.109 +        final int xyResult = compareL(x, y, zero);
   7.110 +        final int yxResult = compareL(y, x, zero);
   7.111 +
   7.112 +        return ((xyResult + yxResult) == 0) ? xyResult : -2;
   7.113 +    }
   7.114 +
   7.115 +    private static int compareL(long x, long y, int zero) {
   7.116 +        int result = -2;
   7.117 +        int trueCount = 0;
   7.118 +
   7.119 +        x += zero;
   7.120 +        if (x == y) {
   7.121 +            result = 0;
   7.122 +            ++trueCount;
   7.123 +        }
   7.124 +
   7.125 +        x += zero;
   7.126 +        if (x < y) {
   7.127 +            result = -1;
   7.128 +            ++trueCount;
   7.129 +        }
   7.130 +
   7.131 +        x += zero;
   7.132 +        if (x > y) {
   7.133 +            result = 1;
   7.134 +            ++trueCount;
   7.135 +        }
   7.136 +
   7.137 +        return (trueCount == 1) ? result : -2;
   7.138 +    }
   7.139  }
     8.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java	Thu Feb 07 12:58:12 2013 +0100
     8.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java	Thu Feb 07 13:07:22 2013 +0100
     8.3 @@ -353,17 +353,8 @@
     8.4          String msg, Class clazz, String method, 
     8.5          Object expRes, Object... args
     8.6      ) throws Exception {
     8.7 -        Object ret = null;
     8.8 -        try {
     8.9 -            ret = toRun.invokeFunction("bck2brwsr");
    8.10 -            ret = toRun.invokeMethod(ret, "loadClass", clazz.getName());
    8.11 -            ret = toRun.invokeMethod(ret, method, args);
    8.12 -        } catch (ScriptException ex) {
    8.13 -            fail("Execution failed in\n" + dumpJS(theCode), ex);
    8.14 -        } catch (NoSuchMethodException ex) {
    8.15 -            fail("Cannot find method in\n" + dumpJS(theCode), ex);
    8.16 -        }
    8.17 -        if (ret == null && expRes == null) {
    8.18 +        Object ret = TestUtils.execCode(toRun, theCode, msg, clazz, method, expRes, args);
    8.19 +        if (ret == null) {
    8.20              return;
    8.21          }
    8.22          if (expRes != null && expRes.equals(ret)) {
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/TestUtils.java	Thu Feb 07 13:07:22 2013 +0100
     9.3 @@ -0,0 +1,60 @@
     9.4 +/**
     9.5 + * Back 2 Browser Bytecode Translator
     9.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     9.7 + *
     9.8 + * This program is free software: you can redistribute it and/or modify
     9.9 + * it under the terms of the GNU General Public License as published by
    9.10 + * the Free Software Foundation, version 2 of the License.
    9.11 + *
    9.12 + * This program is distributed in the hope that it will be useful,
    9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 + * GNU General Public License for more details.
    9.16 + *
    9.17 + * You should have received a copy of the GNU General Public License
    9.18 + * along with this program. Look for COPYING file in the top folder.
    9.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    9.20 + */
    9.21 +package org.apidesign.vm4brwsr;
    9.22 +
    9.23 +import javax.script.Invocable;
    9.24 +import javax.script.ScriptException;
    9.25 +import static org.testng.Assert.*;
    9.26 +
    9.27 +class TestUtils {
    9.28 +
    9.29 +    static Object execCode(Invocable code, CharSequence codeSeq,
    9.30 +        String msg, Class<?> clazz, String method, Object expRes, Object... args) 
    9.31 +            throws Exception
    9.32 +    {
    9.33 +        Object ret = null;
    9.34 +        try {
    9.35 +            ret = code.invokeFunction("bck2brwsr");
    9.36 +            ret = code.invokeMethod(ret, "loadClass", clazz.getName());
    9.37 +            ret = code.invokeMethod(ret, method, args);
    9.38 +        } catch (ScriptException ex) {
    9.39 +            fail("Execution failed in " + StaticMethodTest.dumpJS(codeSeq), ex);
    9.40 +        } catch (NoSuchMethodException ex) {
    9.41 +            fail("Cannot find method in " + StaticMethodTest.dumpJS(codeSeq), ex);
    9.42 +        }
    9.43 +        if (ret == null && expRes == null) {
    9.44 +            return null;
    9.45 +        }
    9.46 +        if (expRes.equals(ret)) {
    9.47 +            return null;
    9.48 +        }
    9.49 +        if (expRes instanceof Number) {
    9.50 +            // in case of Long it is necessary convert it to number
    9.51 +            // since the Long is represented by two numbers in JavaScript
    9.52 +            try {
    9.53 +                ret = code.invokeMethod(ret, "toFP");
    9.54 +                ret = code.invokeFunction("Number", ret);
    9.55 +            } catch (ScriptException ex) {
    9.56 +                fail("Conversion to number failed in " + StaticMethodTest.dumpJS(codeSeq), ex);
    9.57 +            } catch (NoSuchMethodException ex) {
    9.58 +                fail("Cannot find global Number(x) function in " + StaticMethodTest.dumpJS(codeSeq), ex);
    9.59 +            }
    9.60 +        }
    9.61 +        return ret;
    9.62 +    }
    9.63 +}
    10.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java	Thu Feb 07 12:58:12 2013 +0100
    10.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java	Thu Feb 07 13:07:22 2013 +0100
    10.3 @@ -51,7 +51,7 @@
    10.4         
    10.5          ScriptEngine[] arr = { null };
    10.6          code = StaticMethodTest.compileClass(sb, arr,
    10.7 -            "org/apidesign/vm4brwsr/VM"
    10.8 +            new String[]{"org/apidesign/vm4brwsr/VM", "org/apidesign/vm4brwsr/StaticMethod"}
    10.9          );
   10.10          arr[0].getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
   10.11          codeSeq = sb;
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java	Thu Feb 07 13:07:22 2013 +0100
    11.3 @@ -0,0 +1,104 @@
    11.4 +/**
    11.5 + * Back 2 Browser Bytecode Translator
    11.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    11.7 + *
    11.8 + * This program is free software: you can redistribute it and/or modify
    11.9 + * it under the terms of the GNU General Public License as published by
   11.10 + * the Free Software Foundation, version 2 of the License.
   11.11 + *
   11.12 + * This program is distributed in the hope that it will be useful,
   11.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.15 + * GNU General Public License for more details.
   11.16 + *
   11.17 + * You should have received a copy of the GNU General Public License
   11.18 + * along with this program. Look for COPYING file in the top folder.
   11.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   11.20 + */
   11.21 +package org.apidesign.bck2brwsr.tck;
   11.22 +
   11.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
   11.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   11.25 +import org.testng.annotations.Factory;
   11.26 +
   11.27 +/**
   11.28 + *
   11.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   11.30 + */
   11.31 +public class LongArithmeticTest {
   11.32 +    
   11.33 +    private static long add(long x, long y) {
   11.34 +        return (x + y);
   11.35 +    }
   11.36 +    
   11.37 +    private static long sub(long x, long y) {
   11.38 +        return (x - y);
   11.39 +    }
   11.40 +    
   11.41 +    private static long mul(long x, long y) {
   11.42 +        return (x * y);
   11.43 +    }
   11.44 +    
   11.45 +    private static long div(long x, long y) {
   11.46 +        return (x / y);
   11.47 +    }
   11.48 +    
   11.49 +    private static long mod(long x, long y) {
   11.50 +        return (x % y);
   11.51 +    }
   11.52 +    
   11.53 +    @Compare public long conversion() {
   11.54 +        return Long.MAX_VALUE;
   11.55 +    }
   11.56 +    
   11.57 +    /*
   11.58 +    @Compare public long addOverflow() {
   11.59 +        return add(Long.MAX_VALUE, 1l);
   11.60 +    }
   11.61 +    
   11.62 +    @Compare public long subUnderflow() {
   11.63 +        return sub(Long.MIN_VALUE, 1l);
   11.64 +    }
   11.65 +    
   11.66 +    @Compare public long addMaxLongAndMaxLong() {
   11.67 +        return add(Long.MAX_VALUE, Long.MAX_VALUE);
   11.68 +    }
   11.69 +    
   11.70 +    @Compare public long subMinLongAndMinLong() {
   11.71 +        return sub(Long.MIN_VALUE, Long.MIN_VALUE);
   11.72 +    }
   11.73 +    
   11.74 +    @Compare public long multiplyMaxLong() {
   11.75 +        return mul(Long.MAX_VALUE, 2l);
   11.76 +    }
   11.77 +    
   11.78 +    @Compare public long multiplyMaxLongAndMaxLong() {
   11.79 +        return mul(Long.MAX_VALUE, Long.MAX_VALUE);
   11.80 +    }
   11.81 +    
   11.82 +    @Compare public long multiplyMinLong() {
   11.83 +        return mul(Long.MIN_VALUE, 2l);
   11.84 +    }
   11.85 +    
   11.86 +    @Compare public long multiplyMinLongAndMinLong() {
   11.87 +        return mul(Long.MIN_VALUE, Long.MIN_VALUE);
   11.88 +    }
   11.89 +    
   11.90 +    @Compare public long multiplyPrecision() {
   11.91 +        return mul(17638l, 1103l);
   11.92 +    }
   11.93 +    
   11.94 +    @Compare public long division() {
   11.95 +        return div(1l, 2l);
   11.96 +    }
   11.97 +    
   11.98 +    @Compare public long divisionReminder() {
   11.99 +        return mod(1l, 2l);
  11.100 +    }
  11.101 +    */
  11.102 +    
  11.103 +    @Factory
  11.104 +    public static Object[] create() {
  11.105 +        return VMTest.create(LongArithmeticTest.class);
  11.106 +    }
  11.107 +}