Speeding up sieve by directly resolving all 32-bit number operations
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 25 Jan 2016 08:14:42 +0100
changeset 18584dea14fafc31
parent 1857 f1344425bcb1
child 1859 727d3be7e03c
Speeding up sieve by directly resolving all 32-bit number operations
rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js
rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/NumberOperations.java
     1.1 --- a/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Mon Jan 25 06:40:40 2016 +0100
     1.2 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Mon Jan 25 08:14:42 2016 +0100
     1.3 @@ -4,25 +4,9 @@
     1.4      function add32(x, y) {
     1.5          return (x + y) | 0;
     1.6      };
     1.7 -    numberPrototype.mul32 = function(x) {
     1.8 -        return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
     1.9 +    function mul32(x, y) {
    1.10 +        return (((x * (y >> 16)) << 16) + x * (y & 0xFFFF)) | 0;
    1.11      };
    1.12 -    numberPrototype.div32 = function(x) {
    1.13 -        if (x === 0) {
    1.14 -            __handleDivByZero();
    1.15 -        }
    1.16 -
    1.17 -        return (this / x) | 0;
    1.18 -    }
    1.19 -
    1.20 -    numberPrototype.mod32 = function(x) {
    1.21 -        if (x === 0) {
    1.22 -            __handleDivByZero();
    1.23 -        }
    1.24 -
    1.25 -        return (this % x);
    1.26 -    }
    1.27 -
    1.28      var __m32 = 0xFFFFFFFF;
    1.29  
    1.30      numberPrototype.next32 = function(low) {
    1.31 @@ -116,7 +100,7 @@
    1.32      };
    1.33  
    1.34      numberPrototype.mul64 = function(x) {
    1.35 -        var low = this.mul32(x);
    1.36 +        var low = mul32(this, x);
    1.37          low += (low < 0) ? (__m32 + 1) : 0;
    1.38          // first count upper 32 bits of (this.low * x.low)
    1.39          var hi_hi = 0;
    1.40 @@ -134,8 +118,8 @@
    1.41          }
    1.42          var hi = (hi_hi << 16) + hi_low;
    1.43  
    1.44 -        var m1 = this.high32().mul32(x);
    1.45 -        var m2 = this.mul32(x.high32());
    1.46 +        var m1 = mul32(this.high32(), x);
    1.47 +        var m2 = mul32(this, x.high32());
    1.48          hi = add32(add32(hi, m1), m2);
    1.49  
    1.50          return hi.next32(low);
     2.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Jan 25 06:40:40 2016 +0100
     2.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Jan 25 08:14:42 2016 +0100
     2.3 @@ -41,6 +41,7 @@
     2.4      private final StringArray classRefs = new StringArray();
     2.5      private boolean outChanged;
     2.6      private boolean callbacks;
     2.7 +    private final NumberOperations numbers = new NumberOperations();
     2.8  
     2.9      protected ByteCodeToJavaScript(Appendable out) {
    2.10          this.out = out;
    2.11 @@ -293,6 +294,7 @@
    2.12              append("\n    m.access = " + m.getAccess()).append(";");
    2.13              append("\n    m.cls = CLS;");
    2.14          }
    2.15 +        append(numbers.generate());
    2.16          append("\n    c.constructor = CLS;");
    2.17          append("\n    function ").append(className).append("fillInstOf(x) {");
    2.18          String instOfName = "$instOf_" + className;
    2.19 @@ -754,7 +756,7 @@
    2.20                      smapper.replace(this, VarType.DOUBLE, "(@1 - @2)", smapper.getD(1), smapper.popD());
    2.21                      break;
    2.22                  case opc_imul:
    2.23 -                    smapper.replace(this, VarType.INTEGER, "(@1).mul32(@2)", smapper.getI(1), smapper.popI());
    2.24 +                    smapper.replace(this, VarType.INTEGER, numbers.mul32(), smapper.getI(1), smapper.popI());
    2.25                      break;
    2.26                  case opc_lmul:
    2.27                      smapper.replace(this, VarType.LONG, "(@1).mul64(@2)", smapper.getL(1), smapper.popL());
    2.28 @@ -766,7 +768,7 @@
    2.29                      smapper.replace(this, VarType.DOUBLE, "(@1 * @2)", smapper.getD(1), smapper.popD());
    2.30                      break;
    2.31                  case opc_idiv:
    2.32 -                    smapper.replace(this, VarType.INTEGER, "(@1).div32(@2)",
    2.33 +                    smapper.replace(this, VarType.INTEGER, numbers.div32(),
    2.34                           smapper.getI(1), smapper.popI());
    2.35                      break;
    2.36                  case opc_ldiv:
    2.37 @@ -780,7 +782,7 @@
    2.38                      smapper.replace(this, VarType.DOUBLE, "(@1 / @2)", smapper.getD(1), smapper.popD());
    2.39                      break;
    2.40                  case opc_irem:
    2.41 -                    smapper.replace(this, VarType.INTEGER, "(@1).mod32(@2)",
    2.42 +                    smapper.replace(this, VarType.INTEGER, numbers.mod32(),
    2.43                           smapper.getI(1), smapper.popI());
    2.44                      break;
    2.45                  case opc_lrem:
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/NumberOperations.java	Mon Jan 25 08:14:42 2016 +0100
     3.3 @@ -0,0 +1,86 @@
     3.4 +/**
     3.5 + * Back 2 Browser Bytecode Translator
     3.6 + * Copyright (C) 2012-2015 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, version 2 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU General Public License
    3.18 + * along with this program. Look for COPYING file in the top folder.
    3.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    3.20 + */
    3.21 +package org.apidesign.vm4brwsr;
    3.22 +
    3.23 +final class NumberOperations {
    3.24 +    private static final int DIV32 = 1;
    3.25 +    private static final int MOD32 = 2;
    3.26 +    private static final int MUL32 = 4;
    3.27 +
    3.28 +    private int used;
    3.29 +
    3.30 +    public String mul32() {
    3.31 +        used |= MUL32;
    3.32 +        return "__mul32(@1,@2)";
    3.33 +    }
    3.34 +    public String div32() {
    3.35 +        used |= DIV32;
    3.36 +        return "__div32(@1,@2)";
    3.37 +    }
    3.38 +
    3.39 +    public String mod32() {
    3.40 +        used |= MOD32;
    3.41 +        return "__mod32(@1,@2)";
    3.42 +    }
    3.43 +
    3.44 +    public String generate() {
    3.45 +        if (used == 0) {
    3.46 +            return "";
    3.47 +        }
    3.48 +        StringBuilder sb = new StringBuilder();
    3.49 +        if ((used & MUL32) != 0) {
    3.50 +            sb.append(
    3.51 +                "    __mul32 = function(x, y) {\n" +
    3.52 +                "        return (((x * (y >> 16)) << 16) + x * (y & 0xFFFF)) | 0;\n" +
    3.53 +                "    };\n" +
    3.54 +                ""
    3.55 +            );
    3.56 +        }
    3.57 +        if ((used & (MOD32 | DIV32)) != 0) {
    3.58 +            sb.append(
    3.59 +                "    function __handleDivByZero() {\n" +
    3.60 +                "        var exception = new vm.java_lang_ArithmeticException;\n" +
    3.61 +                "        vm.java_lang_ArithmeticException(false).constructor\n" +
    3.62 +                "          .cons__VLjava_lang_String_2.call(exception, \"/ by zero\");\n" +
    3.63 +                "\n" +
    3.64 +                "        throw exception;\n" +
    3.65 +                "    }\n" +
    3.66 +                ""
    3.67 +            );
    3.68 +        }
    3.69 +        if ((used & MOD32) != 0) {
    3.70 +            sb.append(
    3.71 +                "    function __mod32(x, y) {\n" +
    3.72 +                "        if (y === 0) __handleDivByZero();\n" +
    3.73 +                "        return (x % y) | 0;\n" +
    3.74 +                "    }\n" +
    3.75 +                ""
    3.76 +            );
    3.77 +        }
    3.78 +        if ((used & DIV32) != 0) {
    3.79 +            sb.append(
    3.80 +                "    function __div32(x, y) {\n" +
    3.81 +                "        if (y === 0) __handleDivByZero();\n" +
    3.82 +                "        return (x / y) | 0;\n" +
    3.83 +                "    }\n" +
    3.84 +                ""
    3.85 +            );
    3.86 +        }
    3.87 +        return sb.toString();
    3.88 +    }
    3.89 +}