Some operations are faster when included in the generated code rather than dispatched to Number.prototype
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 25 Jan 2016 06:40:40 +0100
changeset 1857f1344425bcb1
parent 1856 9cdc403018b5
child 1858 4dea14fafc31
Some operations are faster when included in the generated code rather than dispatched to Number.prototype
benchmarks/sieve/src/test/java/org/apidesign/benchmark/sieve/SieveTest.java
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
     1.1 --- a/benchmarks/sieve/src/test/java/org/apidesign/benchmark/sieve/SieveTest.java	Mon Jan 25 05:53:21 2016 +0100
     1.2 +++ b/benchmarks/sieve/src/test/java/org/apidesign/benchmark/sieve/SieveTest.java	Mon Jan 25 06:40:40 2016 +0100
     1.3 @@ -45,6 +45,16 @@
     1.4          log("oneThousand in " + took + " ms");
     1.5          return res;
     1.6      }
     1.7 +
     1.8 +    @Compare(scripting = false)
     1.9 +    public int fiveThousand() throws IOException {
    1.10 +        SieveTest sieve = new SieveTest();
    1.11 +        int now = time();
    1.12 +        int res = sieve.compute(5000);
    1.13 +        int took = time() - now;
    1.14 +        log("oneThousand in " + took + " ms");
    1.15 +        return res;
    1.16 +    }
    1.17      
    1.18      @Factory
    1.19      public static Object[] create() {
    1.20 @@ -54,5 +64,6 @@
    1.21      @JavaScriptBody(args = { "msg" }, body = "if (typeof console !== 'undefined') console.log(msg);")
    1.22      @Override
    1.23      protected void log(String msg) {
    1.24 +        System.err.println(msg);
    1.25      }
    1.26  }
     2.1 --- a/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Mon Jan 25 05:53:21 2016 +0100
     2.2 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Mon Jan 25 06:40:40 2016 +0100
     2.3 @@ -1,25 +1,27 @@
     2.4  // empty line needed here
     2.5  
     2.6  (function(numberPrototype) {
     2.7 -    numberPrototype.add32 = function(x) {
     2.8 -        return (this + x) | 0;
     2.9 -    };
    2.10 -    numberPrototype.sub32 = function(x) {
    2.11 -        return (this - x) | 0;
    2.12 +    function add32(x, y) {
    2.13 +        return (x + y) | 0;
    2.14      };
    2.15      numberPrototype.mul32 = function(x) {
    2.16          return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
    2.17      };
    2.18 -    numberPrototype.neg32 = function() {
    2.19 -        return (-this) | 0;
    2.20 -    };
    2.21 +    numberPrototype.div32 = function(x) {
    2.22 +        if (x === 0) {
    2.23 +            __handleDivByZero();
    2.24 +        }
    2.25  
    2.26 -    numberPrototype.toInt8 = function() {
    2.27 -        return (this << 24) >> 24;
    2.28 -    };
    2.29 -    numberPrototype.toInt16 = function() {
    2.30 -        return (this << 16) >> 16;
    2.31 -    };
    2.32 +        return (this / x) | 0;
    2.33 +    }
    2.34 +
    2.35 +    numberPrototype.mod32 = function(x) {
    2.36 +        if (x === 0) {
    2.37 +            __handleDivByZero();
    2.38 +        }
    2.39 +
    2.40 +        return (this % x);
    2.41 +    }
    2.42  
    2.43      var __m32 = 0xFFFFFFFF;
    2.44  
    2.45 @@ -35,9 +37,6 @@
    2.46      numberPrototype.high32 = function() {
    2.47          return this.hi ? this.hi : (Math.floor(this / (__m32 + 1))) | 0;
    2.48      };
    2.49 -    numberPrototype.toInt32 = function() {
    2.50 -        return this | 0;
    2.51 -    };
    2.52      numberPrototype.toFP = function() {
    2.53          return this.hi ? this.hi * (__m32 + 1) + this : this;
    2.54      };
    2.55 @@ -137,7 +136,7 @@
    2.56  
    2.57          var m1 = this.high32().mul32(x);
    2.58          var m2 = this.mul32(x.high32());
    2.59 -        hi = hi.add32(m1).add32(m2);
    2.60 +        hi = add32(add32(hi, m1), m2);
    2.61  
    2.62          return hi.next32(low);
    2.63      };
    2.64 @@ -225,16 +224,6 @@
    2.65          }
    2.66      };
    2.67  
    2.68 -    // keeping for compatibility with generated bck2brwsr.js library files
    2.69 -    // not used since 0.14
    2.70 -    numberPrototype.compare = function(x) {
    2.71 -        if (this == x) {
    2.72 -            return 0;
    2.73 -        } else {
    2.74 -            return (this < x) ? -1 : 1;
    2.75 -        }
    2.76 -    };
    2.77 -
    2.78      numberPrototype.compare64 = function(x) {
    2.79          if (this.high32() === x.high32()) {
    2.80              return (this < x) ? -1 : ((this > x) ? 1 : 0);
    2.81 @@ -490,22 +479,6 @@
    2.82          }
    2.83      }
    2.84  
    2.85 -    numberPrototype.div32 = function(x) {
    2.86 -        if (x === 0) {
    2.87 -            __handleDivByZero();
    2.88 -        }
    2.89 -
    2.90 -        return (this / x) | 0;
    2.91 -    }
    2.92 -
    2.93 -    numberPrototype.mod32 = function(x) {
    2.94 -        if (x === 0) {
    2.95 -            __handleDivByZero();
    2.96 -        }
    2.97 -
    2.98 -        return (this % x);
    2.99 -    }
   2.100 -
   2.101      numberPrototype.div64 = function(x) {
   2.102          var negateResult = false;
   2.103          var u, v;
     3.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Jan 25 05:53:21 2016 +0100
     3.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Jan 25 06:40:40 2016 +0100
     3.3 @@ -730,7 +730,7 @@
     3.4                      emit(smapper, this, "var @1 = @2;", lmapper.setD(3), smapper.popD());
     3.5                      break;
     3.6                  case opc_iadd:
     3.7 -                    smapper.replace(this, VarType.INTEGER, "(@1).add32(@2)", smapper.getI(1), smapper.popI());
     3.8 +                    smapper.replace(this, VarType.INTEGER, "(((@1) + (@2)) | 0)", smapper.getI(1), smapper.popI());
     3.9                      break;
    3.10                  case opc_ladd:
    3.11                      smapper.replace(this, VarType.LONG, "(@1).add64(@2)", smapper.getL(1), smapper.popL());
    3.12 @@ -742,7 +742,7 @@
    3.13                      smapper.replace(this, VarType.DOUBLE, "(@1 + @2)", smapper.getD(1), smapper.popD());
    3.14                      break;
    3.15                  case opc_isub:
    3.16 -                    smapper.replace(this, VarType.INTEGER, "(@1).sub32(@2)", smapper.getI(1), smapper.popI());
    3.17 +                    smapper.replace(this, VarType.INTEGER, "(((@1) - (@2)) | 0)", smapper.getI(1), smapper.popI());
    3.18                      break;
    3.19                  case opc_lsub:
    3.20                      smapper.replace(this, VarType.LONG, "(@1).sub64(@2)", smapper.getL(1), smapper.popL());
    3.21 @@ -812,7 +812,7 @@
    3.22                      smapper.replace(this, VarType.LONG, "(@1).xor64(@2)", smapper.getL(1), smapper.popL());
    3.23                      break;
    3.24                  case opc_ineg:
    3.25 -                    smapper.replace(this, VarType.INTEGER, "(@1).neg32()", smapper.getI(0));
    3.26 +                    smapper.replace(this, VarType.INTEGER, "(-(@1))", smapper.getI(0));
    3.27                      break;
    3.28                  case opc_lneg:
    3.29                      smapper.replace(this, VarType.LONG, "(@1).neg64()", smapper.getL(0));
    3.30 @@ -886,7 +886,7 @@
    3.31                      smapper.replace(this, VarType.DOUBLE, "@1", smapper.getI(0));
    3.32                      break;
    3.33                  case opc_l2i:
    3.34 -                    smapper.replace(this, VarType.INTEGER, "(@1).toInt32()", smapper.getL(0));
    3.35 +                    smapper.replace(this, VarType.INTEGER, "((@1) | 0)", smapper.getL(0));
    3.36                      break;
    3.37                      // max int check?
    3.38                  case opc_l2f:
    3.39 @@ -904,7 +904,7 @@
    3.40                           smapper.getD(0));
    3.41                      break;
    3.42                  case opc_f2i:
    3.43 -                    smapper.replace(this, VarType.INTEGER, "(@1).toInt32()",
    3.44 +                    smapper.replace(this, VarType.INTEGER, "((@1) | 0)",
    3.45                           smapper.getF(0));
    3.46                      break;
    3.47                  case opc_f2l:
    3.48 @@ -912,18 +912,18 @@
    3.49                           smapper.getF(0));
    3.50                      break;
    3.51                  case opc_d2i:
    3.52 -                    smapper.replace(this, VarType.INTEGER, "(@1).toInt32()",
    3.53 +                    smapper.replace(this, VarType.INTEGER, "((@1)| 0)",
    3.54                           smapper.getD(0));
    3.55                      break;
    3.56                  case opc_d2l:
    3.57                      smapper.replace(this, VarType.LONG, "(@1).toLong()", smapper.getD(0));
    3.58                      break;
    3.59                  case opc_i2b:
    3.60 -                    smapper.replace(this, VarType.INTEGER, "(@1).toInt8()", smapper.getI(0));
    3.61 +                    smapper.replace(this, VarType.INTEGER, "(((@1) << 24) >> 24)", smapper.getI(0));
    3.62                      break;
    3.63                  case opc_i2c:
    3.64                  case opc_i2s:
    3.65 -                    smapper.replace(this, VarType.INTEGER, "(@1).toInt16()", smapper.getI(0));
    3.66 +                    smapper.replace(this, VarType.INTEGER, "(((@1) << 16) >> 16)", smapper.getI(0));
    3.67                      break;
    3.68                  case opc_aconst_null:
    3.69                      smapper.assign(this, VarType.REFERENCE, "null");