# HG changeset patch # User Jaroslav Tulach # Date 1453706082 -3600 # Node ID 4dea14fafc319063052a2e34d7265b335747840c # Parent f1344425bcb1976b69c646b4c42f89cb9238fb03 Speeding up sieve by directly resolving all 32-bit number operations diff -r f1344425bcb1 -r 4dea14fafc31 rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js --- a/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Mon Jan 25 06:40:40 2016 +0100 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Mon Jan 25 08:14:42 2016 +0100 @@ -4,25 +4,9 @@ function add32(x, y) { return (x + y) | 0; }; - numberPrototype.mul32 = function(x) { - return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0; + function mul32(x, y) { + return (((x * (y >> 16)) << 16) + x * (y & 0xFFFF)) | 0; }; - numberPrototype.div32 = function(x) { - if (x === 0) { - __handleDivByZero(); - } - - return (this / x) | 0; - } - - numberPrototype.mod32 = function(x) { - if (x === 0) { - __handleDivByZero(); - } - - return (this % x); - } - var __m32 = 0xFFFFFFFF; numberPrototype.next32 = function(low) { @@ -116,7 +100,7 @@ }; numberPrototype.mul64 = function(x) { - var low = this.mul32(x); + var low = mul32(this, x); low += (low < 0) ? (__m32 + 1) : 0; // first count upper 32 bits of (this.low * x.low) var hi_hi = 0; @@ -134,8 +118,8 @@ } var hi = (hi_hi << 16) + hi_low; - var m1 = this.high32().mul32(x); - var m2 = this.mul32(x.high32()); + var m1 = mul32(this.high32(), x); + var m2 = mul32(this, x.high32()); hi = add32(add32(hi, m1), m2); return hi.next32(low); diff -r f1344425bcb1 -r 4dea14fafc31 rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Jan 25 06:40:40 2016 +0100 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Jan 25 08:14:42 2016 +0100 @@ -41,6 +41,7 @@ private final StringArray classRefs = new StringArray(); private boolean outChanged; private boolean callbacks; + private final NumberOperations numbers = new NumberOperations(); protected ByteCodeToJavaScript(Appendable out) { this.out = out; @@ -293,6 +294,7 @@ append("\n m.access = " + m.getAccess()).append(";"); append("\n m.cls = CLS;"); } + append(numbers.generate()); append("\n c.constructor = CLS;"); append("\n function ").append(className).append("fillInstOf(x) {"); String instOfName = "$instOf_" + className; @@ -754,7 +756,7 @@ smapper.replace(this, VarType.DOUBLE, "(@1 - @2)", smapper.getD(1), smapper.popD()); break; case opc_imul: - smapper.replace(this, VarType.INTEGER, "(@1).mul32(@2)", smapper.getI(1), smapper.popI()); + smapper.replace(this, VarType.INTEGER, numbers.mul32(), smapper.getI(1), smapper.popI()); break; case opc_lmul: smapper.replace(this, VarType.LONG, "(@1).mul64(@2)", smapper.getL(1), smapper.popL()); @@ -766,7 +768,7 @@ smapper.replace(this, VarType.DOUBLE, "(@1 * @2)", smapper.getD(1), smapper.popD()); break; case opc_idiv: - smapper.replace(this, VarType.INTEGER, "(@1).div32(@2)", + smapper.replace(this, VarType.INTEGER, numbers.div32(), smapper.getI(1), smapper.popI()); break; case opc_ldiv: @@ -780,7 +782,7 @@ smapper.replace(this, VarType.DOUBLE, "(@1 / @2)", smapper.getD(1), smapper.popD()); break; case opc_irem: - smapper.replace(this, VarType.INTEGER, "(@1).mod32(@2)", + smapper.replace(this, VarType.INTEGER, numbers.mod32(), smapper.getI(1), smapper.popI()); break; case opc_lrem: diff -r f1344425bcb1 -r 4dea14fafc31 rt/vm/src/main/java/org/apidesign/vm4brwsr/NumberOperations.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/NumberOperations.java Mon Jan 25 08:14:42 2016 +0100 @@ -0,0 +1,86 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012-2015 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.vm4brwsr; + +final class NumberOperations { + private static final int DIV32 = 1; + private static final int MOD32 = 2; + private static final int MUL32 = 4; + + private int used; + + public String mul32() { + used |= MUL32; + return "__mul32(@1,@2)"; + } + public String div32() { + used |= DIV32; + return "__div32(@1,@2)"; + } + + public String mod32() { + used |= MOD32; + return "__mod32(@1,@2)"; + } + + public String generate() { + if (used == 0) { + return ""; + } + StringBuilder sb = new StringBuilder(); + if ((used & MUL32) != 0) { + sb.append( + " __mul32 = function(x, y) {\n" + + " return (((x * (y >> 16)) << 16) + x * (y & 0xFFFF)) | 0;\n" + + " };\n" + + "" + ); + } + if ((used & (MOD32 | DIV32)) != 0) { + sb.append( + " function __handleDivByZero() {\n" + + " var exception = new vm.java_lang_ArithmeticException;\n" + + " vm.java_lang_ArithmeticException(false).constructor\n" + + " .cons__VLjava_lang_String_2.call(exception, \"/ by zero\");\n" + + "\n" + + " throw exception;\n" + + " }\n" + + "" + ); + } + if ((used & MOD32) != 0) { + sb.append( + " function __mod32(x, y) {\n" + + " if (y === 0) __handleDivByZero();\n" + + " return (x % y) | 0;\n" + + " }\n" + + "" + ); + } + if ((used & DIV32) != 0) { + sb.append( + " function __div32(x, y) {\n" + + " if (y === 0) __handleDivByZero();\n" + + " return (x / y) | 0;\n" + + " }\n" + + "" + ); + } + return sb.toString(); + } +}