diff --git a/ChangeLog.markdown b/ChangeLog.markdown index 7cdc91cdfd755..60640b7435309 100644 --- a/ChangeLog.markdown +++ b/ChangeLog.markdown @@ -14,6 +14,13 @@ Current trunk code - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.27.1...incoming - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.27.1...incoming +v1.29.1: 01/07/2015 +------------------- + - Migrated to upstream PNaCl LLVM+Clang 3.5 from the previous 3.4. + +v1.29.0: 01/07/2015 +------------------- + v1.28.3: 01/04/2015 ------------------- - embuilder.py tool diff --git a/emcc b/emcc index 3fae5ec567a12..6bfe5b955b4d3 100755 --- a/emcc +++ b/emcc @@ -70,6 +70,8 @@ LIB_PREFIXES = ('', 'lib') JS_CONTAINING_SUFFIXES = ('js', 'html') +DEFERRED_REPONSE_FILES = ('EMTERPRETIFY_BLACKLIST',) + # Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt # levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get # llvm opt level 3, and speed-wise emcc level 2 is already the slowest/most optimizing @@ -872,7 +874,10 @@ try: for change in settings_changes: key, value = change.split('=') if value[0] == '@': - value = open(value[1:]).read() + if key not in DEFERRED_REPONSE_FILES: + value = open(value[1:]).read() + else: + value = '"' + value + '"' else: value = value.replace('\\', '\\\\') exec('shared.Settings.' + key + ' = ' + value) @@ -897,6 +902,7 @@ try: assert not shared.Settings.RUNTIME_TYPE_INFO, 'RUNTIME_TYPE_INFO is not supported in fastcomp' assert not shared.Settings.CORRUPTION_CHECK, 'CORRUPTION_CHECK is not supported in asm.js mode, which is what fastcomp can emit (you can use non-asm.js mode in non-fastcomp)' assert not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE, 'Linking modules is not supported in fastcomp' + assert not shared.Settings.DLOPEN_SUPPORT, 'dlopen() is not supported yet in fastcomp' except Exception, e: logging.error('Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend') raise e @@ -1034,6 +1040,7 @@ try: shared.Settings.FINALIZE_ASM_JS = 0 shared.Settings.GLOBAL_BASE = 8*256 # keep enough space at the bottom for a full stack frame shared.Settings.SIMPLIFY_IFS = 0 # this is just harmful for emterpreting + shared.Settings.EXPORTED_FUNCTIONS += ['emterpret'] shared.Settings.RUNNING_FASTCOMP = fastcomp @@ -1548,7 +1555,10 @@ try: try: # move temp js to final position, alongside its mem init file shutil.move(final, js_target) - execute([shared.PYTHON, shared.path_from_root('tools', 'emterpretify.py'), js_target, final + '.em.js', memfile, json.dumps(shared.Settings.EMTERPRETIFY_BLACKLIST)]) + args = [shared.PYTHON, shared.path_from_root('tools', 'emterpretify.py'), js_target, final + '.em.js', memfile, json.dumps(shared.Settings.EMTERPRETIFY_BLACKLIST)] + if shared.Settings.EMTERPRETIFY_ASYNC: + args += ['ASYNC=1'] + execute(args) final = final + '.em.js' finally: shared.try_delete(js_target) diff --git a/emscripten-version.txt b/emscripten-version.txt index 940f1321e44d8..6be5a23ede62e 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.29.1 +1.29.2 diff --git a/emscripten.py b/emscripten.py index 8501ab3d42984..72948ae80124f 100755 --- a/emscripten.py +++ b/emscripten.py @@ -1181,6 +1181,11 @@ def keyfunc(other): basic_vars += ['___async', '___async_unwind', '___async_retval', '___async_cur_frame'] asm_runtime_funcs += ['setAsync'] + if settings.get('EMTERPRETIFY'): + asm_runtime_funcs += ['emterpret'] + if settings.get('EMTERPRETIFY_ASYNC'): + asm_runtime_funcs += ['setAsyncState', 'emtStackSave'] + # function tables function_tables = ['dynCall_' + table for table in last_forwarded_json['Functions']['tables']] function_tables_impls = [] @@ -1357,7 +1362,11 @@ def math_fix(g): var nan = +env.NaN, inf = +env.Infinity; var tempInt = 0, tempBigInt = 0, tempBigIntP = 0, tempBigIntS = 0, tempBigIntR = 0.0, tempBigIntI = 0, tempBigIntD = 0, tempValue = 0, tempDouble = 0.0; ''' + ''.join([''' - var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs] + [' var tempFloat = %s;\n' % ('Math_fround(0)' if settings.get('PRECISE_F32') else '0.0')] + ([' const f0 = Math_fround(0);\n'] if settings.get('PRECISE_F32') else []) + ['' if not settings['ALLOW_MEMORY_GROWTH'] else ''' + var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs] + \ + [' var tempFloat = %s;\n' % ('Math_fround(0)' if settings.get('PRECISE_F32') else '0.0')] + \ + [' var asyncState = 0;\n' if settings.get('EMTERPRETIFY_ASYNC') else ''] + \ + ([' const f0 = Math_fround(0);\n'] if settings.get('PRECISE_F32') else []) + \ + ['' if not settings['ALLOW_MEMORY_GROWTH'] else ''' function _emscripten_replace_memory(newBuffer) { if ((byteLength(newBuffer) & 0xffffff || byteLength(newBuffer) <= 0xffffff) || byteLength(newBuffer) > 0x80000000) return false; HEAP8 = new Int8View(newBuffer); @@ -1392,7 +1401,20 @@ def math_fix(g): ''' + (''' function setAsync() { ___async = 1; -}''' if need_asyncify else '') + ''' +}''' if need_asyncify else '') + (''' +function emterpret(pc) { // this will be replaced when the emterpreter code is generated; adding it here allows validation until then + pc = pc | 0; + assert(0); +} +''' if settings['EMTERPRETIFY'] else '') + (''' +function setAsyncState(x) { + x = x | 0; + asyncState = x; +} +function emtStackSave() { + return EMTSTACKTOP|0; +} +''' if settings['EMTERPRETIFY_ASYNC'] else '') + ''' function setThrew(threw, value) { threw = threw|0; value = value|0; diff --git a/site/source/docs/getting_started/FAQ.rst b/site/source/docs/getting_started/FAQ.rst index 7a70ccbb3ddb6..53e88c79fe06d 100644 --- a/site/source/docs/getting_started/FAQ.rst +++ b/site/source/docs/getting_started/FAQ.rst @@ -37,8 +37,8 @@ In most cases you will be able to use your project's current build system with E -Why is code compilation so slow? -================================ +Why is code compilation slow? +============================= Emscripten makes some trade-offs that make the generated code faster and smaller, at the cost of longer compilation times. For example, we build parts of the standard library along with your code, which enables some additional optimizations, but takes a little longer to compile. @@ -60,6 +60,7 @@ The main tips for improving build time are: - Emscripten can run some passes in parallel (specifically, the JavaScript optimisations). Increasing the number of cores results in an almost linear improvement. - Emscripten will automatically use more cores if they are available. You can control how many cores are used with ``EMCC_CORES=N`` (this is useful if you have many cores but relatively less memory). +- Make sure that the native optimizer is being used, which greatly speeds up optimized builds as of 1.28.2. ``EMCC_DEBUG=1`` output should not report errors about the native optimizer failing to build or not being used because of a previous failed build (if it previously failed, do ``emcc --clear-cache`` then compile your file again, and the optimizer will be automatically rebuilt). Why does my code run slowly? @@ -70,8 +71,8 @@ Make sure you optimize code by building with ``-O2`` (even more :ref:`aggressive .. note: This is necessary both for each source file, and for the final stage of linking and compiling to JavaScript. For more information see :ref:`Building-Projects` and :ref:`Optimizing-Code`. -Why is my compiled code so big? -=============================== +Why is my compiled code big? +============================ Make sure you build with ``-O2`` so code is optimized and minified. You should also set up gzip compression on your webserver, which all browsers now support. @@ -146,7 +147,9 @@ How do I link against system libraries like SDL, boost, etc.? System libraries that are included with Emscripten are automatically linked when you compile (just the necessary parts). This includes *libc*, *libc++* (C++ standard library) and :term:`SDL`. -Libraries not included with Emscripten (like Boost) must be compiled and linked with the program just as if they were a module in the project. For example, see how `BananaBread links in libz `_. +Libraries not included with Emscripten (like Boost) must be compiled and linked with the program just as if they were a module in the project. + +There is a set of libraries ported to Emscripten for convenient use, Emscripten Ports. See :ref:`Building-Projects` Another option is to implement needed C APIs as JavaScript librarys (see ``--js-library`` in :ref:`emcc ` and :ref:`implement-c-in-javascript`). Emscripten itself does this for *libc* (not including *malloc*) and :term:`SDL` (but not *libc++* or *malloc*). @@ -156,6 +159,14 @@ Another option is to implement needed C APIs as JavaScript librarys (see ``--js- - In the specific case of *Boost*, if you only need the boost headers then you don't need to compile anything. +What are my options for audio playback? +======================================= + +Emscripten has partial support for SDL (1, not 2) audio, and OpenAL. + +To use SDL audio, include it as ``#include ``. You can use it that way alongside SDL1, SDL2, or another library for platform integration. + + How can my compiled program access files? ========================================= diff --git a/src/compiler.js b/src/compiler.js index 4fc2ca66bf3bc..af535702739e7 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -147,7 +147,11 @@ if (settings_file) { var value = settings[key]; if (value[0] == '@') { // response file type thing, workaround for large inputs: value is @path-to-file - value = JSON.parse(read(value.substr(1))); + try { + value = JSON.parse(read(value.substr(1))); + } catch(e) { + // continue normally; assume it is not a response file + } } eval(key + ' = ' + JSON.stringify(value)); } diff --git a/src/ecmascript_simd.js b/src/ecmascript_simd.js index f2c9ec682acf1..ddd613d3e2d89 100644 --- a/src/ecmascript_simd.js +++ b/src/ecmascript_simd.js @@ -47,20 +47,12 @@ if (typeof Math.fround !== 'undefined') { } } -_SIMD_PRIVATE.minNum = function(x, y) { - return x != x ? y : - y != y ? x : - Math.min(x, y); -} +// Type checking functions. -_SIMD_PRIVATE.maxNum = function(x, y) { - return x != x ? y : - y != y ? x : - Math.max(x, y); +_SIMD_PRIVATE.isNumber = function(o) { + return typeof o === "number" || (typeof o === "object" && o.constructor === Number); } -// Type checking functions. - _SIMD_PRIVATE.isTypedArray = function(o) { return (o instanceof Int8Array) || (o instanceof Uint8Array) || @@ -72,12 +64,31 @@ _SIMD_PRIVATE.isTypedArray = function(o) { (o instanceof Float32Array) || (o instanceof Float64Array) || (o instanceof Int32x4Array) || - (o instanceof Float32x4Array) || - (o instanceof Float64x2Array); + (o instanceof Float32x4Array); } -_SIMD_PRIVATE.isNumber = function(o) { - return typeof o == "number" || (typeof o == "object" && o.constructor === Number); +_SIMD_PRIVATE.isArrayBuffer = function(o) { + return (o instanceof ArrayBuffer); +} + +_SIMD_PRIVATE.minNum = function(x, y) { + return x != x ? y : + y != y ? x : + Math.min(x, y); +} + +_SIMD_PRIVATE.maxNum = function(x, y) { + return x != x ? y : + y != y ? x : + Math.max(x, y); +} + +_SIMD_PRIVATE.tobool = function(x) { + return x < 0; +} + +_SIMD_PRIVATE.frombool = function(x) { + return !x - 1; } // Save/Restore utilities for implementing bitwise conversions. @@ -176,8 +187,9 @@ if (typeof SIMD.float32x4 === "undefined") { */ SIMD.float32x4 = function(x, y, z, w) { if (arguments.length == 1) { - if (!(x instanceof SIMD.float32x4)) + if (!(x instanceof SIMD.float32x4)) { throw new TypeError("argument is not a float32x4."); + } return x; } @@ -206,16 +218,19 @@ if (typeof SIMD.float32x4 === "undefined") { Object.defineProperty(SIMD.float32x4.prototype, 'w', { get: function() { return this.w_; } }); -} -if (typeof SIMD.float32x4.zero === "undefined") { /** - * Construct a new instance of float32x4 number with 0.0 in all lanes. - * @constructor + * Extract the sign bit from each lane return them in the first 4 bits. */ - SIMD.float32x4.zero = function() { - return SIMD.float32x4(0.0, 0.0, 0.0, 0.0); - } + Object.defineProperty(SIMD.float32x4.prototype, 'signMask', { + get: function() { + var mx = (this.x < 0.0 || 1/this.x === -Infinity); + var my = (this.y < 0.0 || 1/this.y === -Infinity); + var mz = (this.z < 0.0 || 1/this.z === -Infinity); + var mw = (this.w < 0.0 || 1/this.w === -Infinity); + return mx | my << 1 | mz << 2 | mw << 3; + } + }); } if (typeof SIMD.float32x4.splat === "undefined") { @@ -252,17 +267,6 @@ if (typeof SIMD.float32x4.fromInt32x4 === "undefined") { } } -if (typeof SIMD.float32x4.fromUnsignedInt32x4 === "undefined") { - /** - * @param {int32x4} t An instance of int32x4. - * @return {float32x4} An unsigned integer to float conversion copy of t. - */ - SIMD.float32x4.fromUnsignedInt32x4 = function(t) { - t = SIMD.int32x4(t); - return SIMD.float32x4(t.x>>>0, t.y>>>0, t.z>>>0, t.w>>>0); - } -} - if (typeof SIMD.float32x4.fromFloat64x2Bits === "undefined") { /** * @param {float64x2} t An instance of float64x2. @@ -316,8 +320,9 @@ if (typeof SIMD.float64x2 === "undefined") { */ SIMD.float64x2 = function(x, y) { if (arguments.length == 1) { - if (!(x instanceof SIMD.float64x2)) + if (!(x instanceof SIMD.float64x2)) { throw new TypeError("argument is not a float64x2."); + } return x; } @@ -325,7 +330,7 @@ if (typeof SIMD.float64x2 === "undefined") { return new SIMD.float64x2(x, y); } - // Use unary + to force coersion to Number. + // Use unary + to force coercion to Number. this.x_ = +x; this.y_ = +y; } @@ -337,16 +342,17 @@ if (typeof SIMD.float64x2 === "undefined") { Object.defineProperty(SIMD.float64x2.prototype, 'y', { get: function() { return this.y_; } }); -} -if (typeof SIMD.float64x2.zero === "undefined") { /** - * Construct a new instance of float64x2 number with 0.0 in all lanes. - * @constructor + * Extract the sign bit from each lane return them in the first 2 bits. */ - SIMD.float64x2.zero = function() { - return SIMD.float64x2(0.0, 0.0); - } + Object.defineProperty(SIMD.float64x2.prototype, 'signMask', { + get: function() { + var mx = (this.x < 0.0 || 1/this.x === -Infinity); + var my = (this.y < 0.0 || 1/this.y === -Infinity); + return mx | my << 1; + } + }); } if (typeof SIMD.float64x2.splat === "undefined") { @@ -383,17 +389,6 @@ if (typeof SIMD.float64x2.fromInt32x4 === "undefined") { } } -if (typeof SIMD.float64x2.fromUnsignedInt32x4 === "undefined") { - /** - * @param {int32x4} t An instance of int32x4. - * @return {float64x2} A float64x2 with .x>>>0 and .y>>>0 from t - */ - SIMD.float64x2.fromUnsignedInt32x4 = function(t) { - t = SIMD.int32x4(t); - return SIMD.float64x2(t.x>>>0, t.y>>>0); - } -} - if (typeof SIMD.float64x2.fromFloat32x4Bits === "undefined") { /** * @param {float32x4} t An instance of float32x4. @@ -449,8 +444,9 @@ if (typeof SIMD.int32x4 === "undefined") { */ SIMD.int32x4 = function(x, y, z, w) { if (arguments.length == 1) { - if (!(x instanceof SIMD.int32x4)) + if (!(x instanceof SIMD.int32x4)) { throw new TypeError("argument is not a int32x4."); + } return x; } @@ -479,22 +475,41 @@ if (typeof SIMD.int32x4 === "undefined") { Object.defineProperty(SIMD.int32x4.prototype, 'w', { get: function() { return this.w_; } }); -} -if (typeof SIMD.int32x4.zero === "undefined") { + Object.defineProperty(SIMD.int32x4.prototype, 'flagX', { + get: function() { return _SIMD_PRIVATE.tobool(this.x); } + }); + + Object.defineProperty(SIMD.int32x4.prototype, 'flagY', { + get: function() { return _SIMD_PRIVATE.tobool(this.y); } + }); + + Object.defineProperty(SIMD.int32x4.prototype, 'flagZ', { + get: function() { return _SIMD_PRIVATE.tobool(this.z); } + }); + + Object.defineProperty(SIMD.int32x4.prototype, 'flagW', { + get: function() { return _SIMD_PRIVATE.tobool(this.w); } + }); + /** - * Construct a new instance of int32x4 number with 0 in all lanes. - * @constructor + * Extract the sign bit from each lane return them in the first 4 bits. */ - SIMD.int32x4.zero = function() { - return SIMD.int32x4(0, 0, 0, 0); - } + Object.defineProperty(SIMD.int32x4.prototype, 'signMask', { + get: function() { + var mx = _SIMD_PRIVATE.tobool(this.x); + var my = _SIMD_PRIVATE.tobool(this.y); + var mz = _SIMD_PRIVATE.tobool(this.z); + var mw = _SIMD_PRIVATE.tobool(this.w); + return mx | my << 1 | mz << 2 | mw << 3; + } + }); } if (typeof SIMD.int32x4.bool === "undefined") { /** - * Construct a new instance of int32x4 number with 0xFFFFFFFF or 0x0 in each - * lane, depending on the truth value in x, y, z, and w. + * Construct a new instance of int32x4 number with either true or false in each + * lane, depending on the truth values in x, y, z, and w. * @param {boolean} flag used for x lane. * @param {boolean} flag used for y lane. * @param {boolean} flag used for z lane. @@ -502,10 +517,10 @@ if (typeof SIMD.int32x4.bool === "undefined") { * @constructor */ SIMD.int32x4.bool = function(x, y, z, w) { - return SIMD.int32x4(x ? -1 : 0x0, - y ? -1 : 0x0, - z ? -1 : 0x0, - w ? -1 : 0x0); + return SIMD.int32x4(_SIMD_PRIVATE.frombool(x), + _SIMD_PRIVATE.frombool(y), + _SIMD_PRIVATE.frombool(z), + _SIMD_PRIVATE.frombool(w)); } } @@ -532,17 +547,6 @@ if (typeof SIMD.int32x4.fromFloat32x4 === "undefined") { } } -if (typeof SIMD.int32x4.fromFloat32x4ToUnsigned === "undefined") { - /** - * @param {float32x4} t An instance of float32x4. - * @return {int32x4} with an unsigned integer to float conversion of t. - */ - SIMD.int32x4.fromFloat32x4ToUnsigned = function(t) { - t = SIMD.float32x4(t); - return SIMD.int32x4(t.x>>>0, t.y>>>0, t.z>>>0, t.w>>>0); - } -} - if (typeof SIMD.int32x4.fromFloat64x2 === "undefined") { /** * @param {float64x2} t An instance of float64x2. @@ -554,61 +558,6 @@ if (typeof SIMD.int32x4.fromFloat64x2 === "undefined") { } } -if (typeof SIMD.int32x4.fromFloat64x2ToUnsigned === "undefined") { - /** - * @param {float64x2} t An instance of float64x2. - * @return {int32x4} An int32x4 with .x>>>0 and .y>>>0 from t - */ - SIMD.int32x4.fromFloat64x2ToUnsigned = function(t) { - t = SIMD.float64x2(t); - return SIMD.int32x4(t.x>>>0, t.y>>>0, 0, 0); - } -} - -if (typeof SIMD.int32x4.fromInt16x8 === "undefined") { - /** - * @param {int16x8} t An instance of int16x8. - * @return {int32x4} with the s0, s1, s2, and s3 from t, sign-extended - */ - SIMD.int32x4.fromInt16x8 = function(t) { - t = SIMD.int16x8(t); - return SIMD.int32x4(t.s0, t.s1, t.s2, t.s3); - } -} - -if (typeof SIMD.int32x4.fromUnsignedInt8x16 === "undefined") { - /** - * @param {int8x16} t An instance of int8x16. - * @return {int32x4} with the s0, s1, s2, and s3 from t, zero-extended - */ - SIMD.int32x4.fromUnsignedInt8x16 = function(t) { - t = SIMD.int8x16(t); - return SIMD.int32x4(t.s0>>>0, t.s1>>>0, t.s2>>>0, t.s3>>>0); - } -} - -if (typeof SIMD.int32x4.fromUnsignedInt16x8 === "undefined") { - /** - * @param {int16x8} t An instance of int16x8. - * @return {int32x4} with the s0, s1, s2, and s3 from t, zero-extended - */ - SIMD.int32x4.fromUnsignedInt16x8 = function(t) { - t = SIMD.int16x8(t); - return SIMD.int32x4(t.s0>>>0, t.s1>>>0, t.s2>>>0, t.s3>>>0); - } -} - -if (typeof SIMD.int32x4.fromInt8x16 === "undefined") { - /** - * @param {int8x16} t An instance of int8x16. - * @return {int32x4} with the s0, s1, s2, and s3 from t - */ - SIMD.int32x4.fromInt8x16 = function(t) { - t = SIMD.int8x16(t); - return SIMD.int32x4(t.s0, t.s1, t.s2, t.s3); - } -} - if (typeof SIMD.int32x4.fromFloat32x4Bits === "undefined") { /** * @param {float32x4} t An instance of float32x4. @@ -668,9 +617,10 @@ if (typeof SIMD.int16x8 === "undefined") { */ SIMD.int16x8 = function(s0, s1, s2, s3, s4, s5, s6, s7) { if (arguments.length == 1) { - if (!(x instanceof SIMD.int16x8)) + if (!(s0 instanceof SIMD.int16x8)) { throw new TypeError("argument is not a int16x8."); - return x; + } + return s0; } if (!(this instanceof SIMD.int16x8)) { @@ -718,21 +668,29 @@ if (typeof SIMD.int16x8 === "undefined") { Object.defineProperty(SIMD.int16x8.prototype, 's7', { get: function() { return this.s7_; } }); -} -if (typeof SIMD.int16x8.zero === "undefined") { /** - * Construct a new instance of int16x8 number with 0 in all lanes. - * @constructor + * Extract the sign bit from each lane return them in the first 8 bits. */ - SIMD.int16x8.zero = function() { - return SIMD.int16x8(0, 0, 0, 0, 0, 0, 0, 0); - } + Object.defineProperty(SIMD.int16x8.prototype, 'signMask', { + get: function() { + var ms0 = (this.s0 & 0x8000) >>> 15; + var ms1 = (this.s1 & 0x8000) >>> 15; + var ms2 = (this.s2 & 0x8000) >>> 15; + var ms3 = (this.s3 & 0x8000) >>> 15; + var ms4 = (this.s4 & 0x8000) >>> 15; + var ms5 = (this.s5 & 0x8000) >>> 15; + var ms6 = (this.s6 & 0x8000) >>> 15; + var ms7 = (this.s7 & 0x8000) >>> 15; + return ms0 | ms1 << 1 | ms2 << 2 | ms3 << 3 | + ms4 << 4 | ms5 << 5 | ms6 << 6 | ms7 << 7; + } + }); } if (typeof SIMD.int16x8.bool === "undefined") { /** - * Construct a new instance of int16x8 number with 0xFFFF or 0x0 in each + * Construct a new instance of int16x8 number with true or false in each * lane, depending on the truth value in s0, s1, s2, s3, s4, s5, s6, and s7. * @param {boolean} flag used for s0 lane. * @param {boolean} flag used for s1 lane. @@ -807,8 +765,8 @@ if (typeof SIMD.int16x8.fromInt8x16Bits === "undefined") { * @return {int16x8} a bit-wise copy of t as a int16x8. */ SIMD.int16x8.fromInt8x16Bits = function(t) { - saveInt8x16(t); - return restoreInt16x8(); + _SIMD_PRIVATE.saveInt8x16(t); + return _SIMD_PRIVATE.restoreInt16x8(); } } @@ -836,9 +794,10 @@ if (typeof SIMD.int8x16 === "undefined") { SIMD.int8x16 = function(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15) { if (arguments.length == 1) { - if (!(x instanceof SIMD.int8x16)) + if (!(s0 instanceof SIMD.int8x16)) { throw new TypeError("argument is not a int8x16."); - return x; + } + return s0; } if (!(this instanceof SIMD.int8x16)) { @@ -927,22 +886,39 @@ if (typeof SIMD.int8x16 === "undefined") { Object.defineProperty(SIMD.int8x16.prototype, 's15', { get: function() { return this.s15_; } }); -} -if (typeof SIMD.int8x16.zero === "undefined") { /** - * Construct a new instance of int8x16 number with 0 in all lanes. - * @constructor + * Extract the sign bit from each lane return them in the first 16 bits. */ - SIMD.int8x16.zero = function() { - return SIMD.int8x16(0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0); - } + Object.defineProperty(SIMD.int8x16.prototype, 'signMask', { + get: function() { + var ms0 = (this.s0 & 0x80) >>> 7; + var ms1 = (this.s1 & 0x80) >>> 7; + var ms2 = (this.s2 & 0x80) >>> 7; + var ms3 = (this.s3 & 0x80) >>> 7; + var ms4 = (this.s4 & 0x80) >>> 7; + var ms5 = (this.s5 & 0x80) >>> 7; + var ms6 = (this.s6 & 0x80) >>> 7; + var ms7 = (this.s7 & 0x80) >>> 7; + var ms8 = (this.s8 & 0x80) >>> 7; + var ms9 = (this.s9 & 0x80) >>> 7; + var ms10 = (this.s10 & 0x80) >>> 7; + var ms11 = (this.s11 & 0x80) >>> 7; + var ms12 = (this.s12 & 0x80) >>> 7; + var ms13 = (this.s13 & 0x80) >>> 7; + var ms14 = (this.s14 & 0x80) >>> 7; + var ms15 = (this.s15 & 0x80) >>> 7; + return ms0 | ms1 << 1 | ms2 << 2 | ms3 << 3 | + ms4 << 4 | ms5 << 5 | ms6 << 6 | ms7 << 7 | + ms8 << 8 | ms9 << 9 | ms10 << 10 | ms11 << 11 | + ms12 << 12 | ms13 << 13 | ms14 << 14 | ms15 << 15; + } + }); } if (typeof SIMD.int8x16.bool === "undefined") { /** - * Construct a new instance of int8x16 number with 0xFF or 0x0 in each + * Construct a new instance of int8x16 number with true or false in each * lane, depending on the truth value in s0, s1, s2, s3, s4, s5, s6, s7, * s8, s9, s10, s11, s12, s13, s14, and s15. * @param {boolean} flag used for s0 lane. @@ -1025,8 +1001,8 @@ if (typeof SIMD.int8x16.fromInt32x4Bits === "undefined") { * @return {int8x16} a bit-wise copy of t as a int8x16. */ SIMD.int8x16.fromInt32x4Bits = function(t) { - saveInt32x4(t); - return restoreInt8x16(); + _SIMD_PRIVATE.saveInt32x4(t); + return _SIMD_PRIVATE.restoreInt8x16(); } } @@ -1036,16 +1012,17 @@ if (typeof SIMD.int8x16.fromInt16x8Bits === "undefined") { * @return {int8x16} a bit-wise copy of t as a int8x16. */ SIMD.int8x16.fromInt16x8Bits = function(t) { - saveInt16x8(t); - return restoreInt8x16(); + _SIMD_PRIVATE.saveInt16x8(t); + return _SIMD_PRIVATE.restoreInt8x16(); } } if (typeof SIMD.float32x4.abs === "undefined") { /** - * @return {float32x4} New instance of float32x4 with absolute values of - * t. - */ + * @param {float32x4} t An instance of float32x4. + * @return {float32x4} New instance of float32x4 with absolute values of + * t. + */ SIMD.float32x4.abs = function(t) { t = SIMD.float32x4(t); return SIMD.float32x4(Math.abs(t.x), Math.abs(t.y), Math.abs(t.z), @@ -1055,6 +1032,7 @@ if (typeof SIMD.float32x4.abs === "undefined") { if (typeof SIMD.float32x4.neg === "undefined") { /** + * @param {float32x4} t An instance of float32x4. * @return {float32x4} New instance of float32x4 with negated values of * t. */ @@ -1066,6 +1044,8 @@ if (typeof SIMD.float32x4.neg === "undefined") { if (typeof SIMD.float32x4.add === "undefined") { /** + * @param {float32x4} a An instance of float32x4. + * @param {float32x4} b An instance of float32x4. * @return {float32x4} New instance of float32x4 with a + b. */ SIMD.float32x4.add = function(a, b) { @@ -1077,6 +1057,8 @@ if (typeof SIMD.float32x4.add === "undefined") { if (typeof SIMD.float32x4.sub === "undefined") { /** + * @param {float32x4} a An instance of float32x4. + * @param {float32x4} b An instance of float32x4. * @return {float32x4} New instance of float32x4 with a - b. */ SIMD.float32x4.sub = function(a, b) { @@ -1088,6 +1070,8 @@ if (typeof SIMD.float32x4.sub === "undefined") { if (typeof SIMD.float32x4.mul === "undefined") { /** + * @param {float32x4} a An instance of float32x4. + * @param {float32x4} b An instance of float32x4. * @return {float32x4} New instance of float32x4 with a * b. */ SIMD.float32x4.mul = function(a, b) { @@ -1099,6 +1083,8 @@ if (typeof SIMD.float32x4.mul === "undefined") { if (typeof SIMD.float32x4.div === "undefined") { /** + * @param {float32x4} a An instance of float32x4. + * @param {float32x4} b An instance of float32x4. * @return {float32x4} New instance of float32x4 with a / b. */ SIMD.float32x4.div = function(a, b) { @@ -1110,6 +1096,9 @@ if (typeof SIMD.float32x4.div === "undefined") { if (typeof SIMD.float32x4.clamp === "undefined") { /** + * @param {float32x4} t An instance of float32x4. + * @param {float32x4} lowerLimit An instance of float32x4. + * @param {float32x4} upperLimit An instance of float32x4. * @return {float32x4} New instance of float32x4 with t's values clamped * between lowerLimit and upperLimit. */ @@ -1131,6 +1120,8 @@ if (typeof SIMD.float32x4.clamp === "undefined") { if (typeof SIMD.float32x4.min === "undefined") { /** + * @param {float32x4} t An instance of float32x4. + * @param {float32x4} other An instance of float32x4. * @return {float32x4} New instance of float32x4 with the minimum value of * t and other. */ @@ -1147,6 +1138,8 @@ if (typeof SIMD.float32x4.min === "undefined") { if (typeof SIMD.float32x4.max === "undefined") { /** + * @param {float32x4} t An instance of float32x4. + * @param {float32x4} other An instance of float32x4. * @return {float32x4} New instance of float32x4 with the maximum value of * t and other. */ @@ -1163,6 +1156,8 @@ if (typeof SIMD.float32x4.max === "undefined") { if (typeof SIMD.float32x4.minNum === "undefined") { /** + * @param {float32x4} t An instance of float32x4. + * @param {float32x4} other An instance of float32x4. * @return {float32x4} New instance of float32x4 with the minimum value of * t and other, preferring numbers over NaNs. */ @@ -1179,6 +1174,8 @@ if (typeof SIMD.float32x4.minNum === "undefined") { if (typeof SIMD.float32x4.maxNum === "undefined") { /** + * @param {float32x4} t An instance of float32x4. + * @param {float32x4} other An instance of float32x4. * @return {float32x4} New instance of float32x4 with the maximum value of * t and other, preferring numbers over NaNs. */ @@ -1195,6 +1192,7 @@ if (typeof SIMD.float32x4.maxNum === "undefined") { if (typeof SIMD.float32x4.reciprocal === "undefined") { /** + * @param {float32x4} t An instance of float32x4. * @return {float32x4} New instance of float32x4 with reciprocal value of * t. */ @@ -1206,6 +1204,7 @@ if (typeof SIMD.float32x4.reciprocal === "undefined") { if (typeof SIMD.float32x4.reciprocalSqrt === "undefined") { /** + * @param {float32x4} t An instance of float32x4. * @return {float32x4} New instance of float32x4 with square root of the * reciprocal value of t. */ @@ -1216,20 +1215,9 @@ if (typeof SIMD.float32x4.reciprocalSqrt === "undefined") { } } -if (typeof SIMD.float32x4.scale === "undefined") { - /** - * @return {float32x4} New instance of float32x4 with values of t - * scaled by s. - */ - SIMD.float32x4.scale = function(t, s) { - t = SIMD.float32x4(t); - var s4 = SIMD.float32x4.splat(s); - return SIMD.float32x4.mul(t,s4); - } -} - if (typeof SIMD.float32x4.sqrt === "undefined") { /** + * @param {float32x4} t An instance of float32x4. * @return {float32x4} New instance of float32x4 with square root of * values of t. */ @@ -1243,10 +1231,10 @@ if (typeof SIMD.float32x4.sqrt === "undefined") { if (typeof SIMD.float32x4.swizzle === "undefined") { /** * @param {float32x4} t An instance of float32x4 to be swizzled. - * @param {integer} x - Index for lane x - * @param {integer} y - Index for lane y - * @param {integer} z - Index for lane z - * @param {integer} w - Index for lane w + * @param {integer} x - Index in t for lane x + * @param {integer} y - Index in t for lane y + * @param {integer} z - Index in t for lane z + * @param {integer} w - Index in t for lane w * @return {float32x4} New instance of float32x4 with lanes swizzled. */ SIMD.float32x4.swizzle = function(t, x, y, z, w) { @@ -1260,8 +1248,7 @@ if (typeof SIMD.float32x4.swizzle === "undefined") { } } -if (typeof SIMD.float32x4.shuffle === "undefined" || - typeof SIMD.float32x4.shuffleMix !== "undefined") { +if (typeof SIMD.float32x4.shuffle === "undefined") { _SIMD_PRIVATE._f32x8 = new Float32Array(8); @@ -1292,6 +1279,7 @@ if (typeof SIMD.float32x4.shuffle === "undefined" || if (typeof SIMD.float32x4.withX === "undefined") { /** + * @param {float32x4} t An instance of float32x4. * @param {double} value used for x lane. * @return {float32x4} New instance of float32x4 with the values in t and * x replaced with {x}. @@ -1304,6 +1292,7 @@ if (typeof SIMD.float32x4.withX === "undefined") { if (typeof SIMD.float32x4.withY === "undefined") { /** + * @param {float32x4} t An instance of float32x4. * @param {double} value used for y lane. * @return {float32x4} New instance of float32x4 with the values in t and * y replaced with {y}. @@ -1316,6 +1305,7 @@ if (typeof SIMD.float32x4.withY === "undefined") { if (typeof SIMD.float32x4.withZ === "undefined") { /** + * @param {float32x4} t An instance of float32x4. * @param {double} value used for z lane. * @return {float32x4} New instance of float32x4 with the values in t and * z replaced with {z}. @@ -1328,6 +1318,7 @@ if (typeof SIMD.float32x4.withZ === "undefined") { if (typeof SIMD.float32x4.withW === "undefined") { /** + * @param {float32x4} t An instance of float32x4. * @param {double} value used for w lane. * @return {float32x4} New instance of float32x4 with the values in t and * w replaced with {w}. @@ -1342,7 +1333,7 @@ if (typeof SIMD.float32x4.lessThan === "undefined") { /** * @param {float32x4} t An instance of float32x4. * @param {float32x4} other An instance of float32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t < other. */ SIMD.float32x4.lessThan = function(t, other) { @@ -1360,7 +1351,7 @@ if (typeof SIMD.float32x4.lessThanOrEqual === "undefined") { /** * @param {float32x4} t An instance of float32x4. * @param {float32x4} other An instance of float32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t <= other. */ SIMD.float32x4.lessThanOrEqual = function(t, other) { @@ -1378,7 +1369,7 @@ if (typeof SIMD.float32x4.equal === "undefined") { /** * @param {float32x4} t An instance of float32x4. * @param {float32x4} other An instance of float32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t == other. */ SIMD.float32x4.equal = function(t, other) { @@ -1396,7 +1387,7 @@ if (typeof SIMD.float32x4.notEqual === "undefined") { /** * @param {float32x4} t An instance of float32x4. * @param {float32x4} other An instance of float32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t != other. */ SIMD.float32x4.notEqual = function(t, other) { @@ -1414,7 +1405,7 @@ if (typeof SIMD.float32x4.greaterThanOrEqual === "undefined") { /** * @param {float32x4} t An instance of float32x4. * @param {float32x4} other An instance of float32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t >= other. */ SIMD.float32x4.greaterThanOrEqual = function(t, other) { @@ -1432,7 +1423,7 @@ if (typeof SIMD.float32x4.greaterThan === "undefined") { /** * @param {float32x4} t An instance of float32x4. * @param {float32x4} other An instance of float32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t > other. */ SIMD.float32x4.greaterThan = function(t, other) { @@ -1450,13 +1441,34 @@ if (typeof SIMD.float32x4.select === "undefined") { /** * @param {int32x4} t Selector mask. An instance of int32x4 * @param {float32x4} trueValue Pick lane from here if corresponding - * selector lane is 0xFFFFFFFF + * selector lane is true * @param {float32x4} falseValue Pick lane from here if corresponding - * selector lane is 0x0 + * selector lane is false * @return {float32x4} Mix of lanes from trueValue or falseValue as * indicated */ SIMD.float32x4.select = function(t, trueValue, falseValue) { + t = SIMD.int32x4(t); + trueValue = SIMD.float32x4(trueValue); + falseValue = SIMD.float32x4(falseValue); + return SIMD.float32x4(_SIMD_PRIVATE.tobool(t.x) ? trueValue.x : falseValue.x, + _SIMD_PRIVATE.tobool(t.y) ? trueValue.y : falseValue.y, + _SIMD_PRIVATE.tobool(t.z) ? trueValue.z : falseValue.z, + _SIMD_PRIVATE.tobool(t.w) ? trueValue.w : falseValue.w); + } +} + +if (typeof SIMD.float32x4.bitselect === "undefined") { + /** + * @param {int32x4} t Selector mask. An instance of int32x4 + * @param {float32x4} trueValue Pick bit from here if corresponding + * selector bit is 1 + * @param {float32x4} falseValue Pick bit from here if corresponding + * selector bit is 0 + * @return {float32x4} Mix of bits from trueValue or falseValue as + * indicated + */ + SIMD.float32x4.bitselect = function(t, trueValue, falseValue) { t = SIMD.int32x4(t); trueValue = SIMD.float32x4(trueValue); falseValue = SIMD.float32x4(falseValue); @@ -1757,9 +1769,10 @@ if (typeof SIMD.float32x4.storeXYZ === "undefined") { if (typeof SIMD.float64x2.abs === "undefined") { /** - * @return {float64x2} New instance of float64x2 with absolute values of - * t. - */ + * @param {float64x2} t An instance of float64x2. + * @return {float64x2} New instance of float64x2 with absolute values of + * t. + */ SIMD.float64x2.abs = function(t) { t = SIMD.float64x2(t); return SIMD.float64x2(Math.abs(t.x), Math.abs(t.y)); @@ -1768,6 +1781,7 @@ if (typeof SIMD.float64x2.abs === "undefined") { if (typeof SIMD.float64x2.neg === "undefined") { /** + * @param {float64x2} t An instance of float64x2. * @return {float64x2} New instance of float64x2 with negated values of * t. */ @@ -1779,6 +1793,8 @@ if (typeof SIMD.float64x2.neg === "undefined") { if (typeof SIMD.float64x2.add === "undefined") { /** + * @param {float64x2} a An instance of float64x2. + * @param {float64x2} b An instance of float64x2. * @return {float64x2} New instance of float64x2 with a + b. */ SIMD.float64x2.add = function(a, b) { @@ -1790,6 +1806,8 @@ if (typeof SIMD.float64x2.add === "undefined") { if (typeof SIMD.float64x2.sub === "undefined") { /** + * @param {float64x2} a An instance of float64x2. + * @param {float64x2} b An instance of float64x2. * @return {float64x2} New instance of float64x2 with a - b. */ SIMD.float64x2.sub = function(a, b) { @@ -1801,6 +1819,8 @@ if (typeof SIMD.float64x2.sub === "undefined") { if (typeof SIMD.float64x2.mul === "undefined") { /** + * @param {float64x2} a An instance of float64x2. + * @param {float64x2} b An instance of float64x2. * @return {float64x2} New instance of float64x2 with a * b. */ SIMD.float64x2.mul = function(a, b) { @@ -1812,6 +1832,8 @@ if (typeof SIMD.float64x2.mul === "undefined") { if (typeof SIMD.float64x2.div === "undefined") { /** + * @param {float64x2} a An instance of float64x2. + * @param {float64x2} b An instance of float64x2. * @return {float64x2} New instance of float64x2 with a / b. */ SIMD.float64x2.div = function(a, b) { @@ -1823,6 +1845,9 @@ if (typeof SIMD.float64x2.div === "undefined") { if (typeof SIMD.float64x2.clamp === "undefined") { /** + * @param {float64x2} t An instance of float64x2. + * @param {float64x2} lowerLimit An instance of float64x2. + * @param {float64x2} upperLimit An instance of float64x2. * @return {float64x2} New instance of float64x2 with t's values clamped * between lowerLimit and upperLimit. */ @@ -1840,6 +1865,8 @@ if (typeof SIMD.float64x2.clamp === "undefined") { if (typeof SIMD.float64x2.min === "undefined") { /** + * @param {float64x2} t An instance of float64x2. + * @param {float64x2} other An instance of float64x2. * @return {float64x2} New instance of float64x2 with the minimum value of * t and other. */ @@ -1854,6 +1881,8 @@ if (typeof SIMD.float64x2.min === "undefined") { if (typeof SIMD.float64x2.max === "undefined") { /** + * @param {float64x2} t An instance of float64x2. + * @param {float64x2} other An instance of float64x2. * @return {float64x2} New instance of float64x2 with the maximum value of * t and other. */ @@ -1868,6 +1897,8 @@ if (typeof SIMD.float64x2.max === "undefined") { if (typeof SIMD.float64x2.minNum === "undefined") { /** + * @param {float64x2} t An instance of float64x2. + * @param {float64x2} other An instance of float64x2. * @return {float64x2} New instance of float64x2 with the minimum value of * t and other, preferring numbers over NaNs. */ @@ -1882,6 +1913,8 @@ if (typeof SIMD.float64x2.minNum === "undefined") { if (typeof SIMD.float64x2.maxNum === "undefined") { /** + * @param {float64x2} t An instance of float64x2. + * @param {float64x2} other An instance of float64x2. * @return {float64x2} New instance of float64x2 with the maximum value of * t and other, preferring numbers over NaNs. */ @@ -1896,6 +1929,7 @@ if (typeof SIMD.float64x2.maxNum === "undefined") { if (typeof SIMD.float64x2.reciprocal === "undefined") { /** + * @param {float64x2} t An instance of float64x2. * @return {float64x2} New instance of float64x2 with reciprocal value of * t. */ @@ -1907,6 +1941,7 @@ if (typeof SIMD.float64x2.reciprocal === "undefined") { if (typeof SIMD.float64x2.reciprocalSqrt === "undefined") { /** + * @param {float64x2} t An instance of float64x2. * @return {float64x2} New instance of float64x2 with square root of the * reciprocal value of t. */ @@ -1916,19 +1951,9 @@ if (typeof SIMD.float64x2.reciprocalSqrt === "undefined") { } } -if (typeof SIMD.float64x2.scale === "undefined") { - /** - * @return {float64x2} New instance of float64x2 with values of t - * scaled by s. - */ - SIMD.float64x2.scale = function(t, s) { - t = SIMD.float64x2(t); - return SIMD.float64x2(s * t.x, s * t.y); - } -} - if (typeof SIMD.float64x2.sqrt === "undefined") { /** + * @param {float64x2} t An instance of float64x2. * @return {float64x2} New instance of float64x2 with square root of * values of t. */ @@ -1941,8 +1966,8 @@ if (typeof SIMD.float64x2.sqrt === "undefined") { if (typeof SIMD.float64x2.swizzle === "undefined") { /** * @param {float64x2} t An instance of float64x2 to be swizzled. - * @param {integer} x - Index for lane x - * @param {integer} y - Index for lane y + * @param {integer} x - Index in t for lane x + * @param {integer} y - Index in t for lane y * @return {float64x2} New instance of float64x2 with lanes swizzled. */ SIMD.float64x2.swizzle = function(t, x, y) { @@ -1954,8 +1979,7 @@ if (typeof SIMD.float64x2.swizzle === "undefined") { } } -if (typeof SIMD.float64x2.shuffle === "undefined" || - typeof SIMD.float64x2.shuffleMix !== "undefined") { +if (typeof SIMD.float64x2.shuffle === "undefined") { _SIMD_PRIVATE._f64x4 = new Float64Array(4); @@ -1980,6 +2004,7 @@ if (typeof SIMD.float64x2.shuffle === "undefined" || if (typeof SIMD.float64x2.withX === "undefined") { /** + * @param {float64x2} t An instance of float64x2. * @param {double} value used for x lane. * @return {float64x2} New instance of float64x2 with the values in t and * x replaced with {x}. @@ -1992,6 +2017,7 @@ if (typeof SIMD.float64x2.withX === "undefined") { if (typeof SIMD.float64x2.withY === "undefined") { /** + * @param {float64x2} t An instance of float64x2. * @param {double} value used for y lane. * @return {float64x2} New instance of float64x2 with the values in t and * y replaced with {y}. @@ -2006,7 +2032,7 @@ if (typeof SIMD.float64x2.lessThan === "undefined") { /** * @param {float64x2} t An instance of float64x2. * @param {float64x2} other An instance of float64x2. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t < other. */ SIMD.float64x2.lessThan = function(t, other) { @@ -2022,7 +2048,7 @@ if (typeof SIMD.float64x2.lessThanOrEqual === "undefined") { /** * @param {float64x2} t An instance of float64x2. * @param {float64x2} other An instance of float64x2. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t <= other. */ SIMD.float64x2.lessThanOrEqual = function(t, other) { @@ -2038,7 +2064,7 @@ if (typeof SIMD.float64x2.equal === "undefined") { /** * @param {float64x2} t An instance of float64x2. * @param {float64x2} other An instance of float64x2. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t == other. */ SIMD.float64x2.equal = function(t, other) { @@ -2054,7 +2080,7 @@ if (typeof SIMD.float64x2.notEqual === "undefined") { /** * @param {float64x2} t An instance of float64x2. * @param {float64x2} other An instance of float64x2. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t != other. */ SIMD.float64x2.notEqual = function(t, other) { @@ -2070,7 +2096,7 @@ if (typeof SIMD.float64x2.greaterThanOrEqual === "undefined") { /** * @param {float64x2} t An instance of float64x2. * @param {float64x2} other An instance of float64x2. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t >= other. */ SIMD.float64x2.greaterThanOrEqual = function(t, other) { @@ -2086,7 +2112,7 @@ if (typeof SIMD.float64x2.greaterThan === "undefined") { /** * @param {float64x2} t An instance of float64x2. * @param {float64x2} other An instance of float64x2. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t > other. */ SIMD.float64x2.greaterThan = function(t, other) { @@ -2102,13 +2128,32 @@ if (typeof SIMD.float64x2.select === "undefined") { /** * @param {int32x4} t Selector mask. An instance of int32x4 * @param {float64x2} trueValue Pick lane from here if corresponding - * selector lanes are 0xFFFFFFFF + * selector lane is true * @param {float64x2} falseValue Pick lane from here if corresponding - * selector lanes are 0x0 + * selector lane is false * @return {float64x2} Mix of lanes from trueValue or falseValue as * indicated */ SIMD.float64x2.select = function(t, trueValue, falseValue) { + t = SIMD.int32x4(t); + trueValue = SIMD.float64x2(trueValue); + falseValue = SIMD.float64x2(falseValue); + return SIMD.float64x2(_SIMD_PRIVATE.tobool(t.x) ? trueValue.x : falseValue.x, + _SIMD_PRIVATE.tobool(t.y) ? trueValue.y : falseValue.y); + } +} + +if (typeof SIMD.float64x2.bitselect === "undefined") { + /** + * @param {int32x4} t Selector mask. An instance of int32x4 + * @param {float64x2} trueValue Pick bit from here if corresponding + * selector bit is 1 + * @param {float64x2} falseValue Pick bit from here if corresponding + * selector bit is 0 + * @return {float64x2} Mix of bits from trueValue or falseValue as + * indicated + */ + SIMD.float64x2.bitselect = function(t, trueValue, falseValue) { t = SIMD.int32x4(t); trueValue = SIMD.float64x2(trueValue); falseValue = SIMD.float64x2(falseValue); @@ -2330,12 +2375,12 @@ if (typeof SIMD.int32x4.mul === "undefined") { if (typeof SIMD.int32x4.swizzle === "undefined") { /** - * @param {int32x4} t An instance of float32x4 to be swizzled. - * @param {integer} x - Index for lane x - * @param {integer} y - Index for lane y - * @param {integer} z - Index for lane z - * @param {integer} w - Index for lane w - * @return {int32x4} New instance of float32x4 with lanes swizzled. + * @param {int32x4} t An instance of int32x4 to be swizzled. + * @param {integer} x - Index in t for lane x + * @param {integer} y - Index in t for lane y + * @param {integer} z - Index in t for lane z + * @param {integer} w - Index in t for lane w + * @return {int32x4} New instance of int32x4 with lanes swizzled. */ SIMD.int32x4.swizzle = function(t, x, y, z, w) { t = SIMD.int32x4(t); @@ -2348,19 +2393,18 @@ if (typeof SIMD.int32x4.swizzle === "undefined") { } } -if (typeof SIMD.int32x4.shuffle === "undefined" || - typeof SIMD.int32x4.shuffleMix !== "undefined") { +if (typeof SIMD.int32x4.shuffle === "undefined") { _SIMD_PRIVATE._i32x8 = new Int32Array(8); /** - * @param {int32x4} t1 An instance of float32x4 to be shuffled. - * @param {int32x4} t2 An instance of float32x4 to be shuffled. + * @param {int32x4} t1 An instance of int32x4 to be shuffled. + * @param {int32x4} t2 An instance of int32x4 to be shuffled. * @param {integer} x - Index in concatenation of t1 and t2 for lane x * @param {integer} y - Index in concatenation of t1 and t2 for lane y * @param {integer} z - Index in concatenation of t1 and t2 for lane z * @param {integer} w - Index in concatenation of t1 and t2 for lane w - * @return {int32x4} New instance of float32x4 with lanes shuffled. + * @return {int32x4} New instance of int32x4 with lanes shuffled. */ SIMD.int32x4.shuffle = function(t1, t2, x, y, z, w) { t1 = SIMD.int32x4(t1); @@ -2374,7 +2418,7 @@ if (typeof SIMD.int32x4.shuffle === "undefined" || storage[5] = t2.y; storage[6] = t2.z; storage[7] = t2.w; - return SIMD.float32x4(storage[x], storage[y], storage[z], storage[w]); + return SIMD.int32x4(storage[x], storage[y], storage[z], storage[w]); } } @@ -2382,9 +2426,9 @@ if (typeof SIMD.int32x4.select === "undefined") { /** * @param {int32x4} t Selector mask. An instance of int32x4 * @param {int32x4} trueValue Pick lane from here if corresponding - * selector lane is 0xFFFFFFFF + * selector lane is true * @param {int32x4} falseValue Pick lane from here if corresponding - * selector lane is 0x0 + * selector lane is false * @return {int32x4} Mix of lanes from trueValue or falseValue as * indicated */ @@ -2392,16 +2436,37 @@ if (typeof SIMD.int32x4.select === "undefined") { t = SIMD.int32x4(t); trueValue = SIMD.int32x4(trueValue); falseValue = SIMD.int32x4(falseValue); - var tr = SIMD.int32x4.and(t, trueValue); - var fr = SIMD.int32x4.and(SIMD.int32x4.not(t), falseValue); - return SIMD.int32x4.or(tr, fr); + return SIMD.int32x4(_SIMD_PRIVATE.tobool(t.x) ? trueValue.x : falseValue.x, + _SIMD_PRIVATE.tobool(t.y) ? trueValue.y : falseValue.y, + _SIMD_PRIVATE.tobool(t.z) ? trueValue.z : falseValue.z, + _SIMD_PRIVATE.tobool(t.w) ? trueValue.w : falseValue.w); } } -if (typeof SIMD.int32x4.withX === "undefined") { +if (typeof SIMD.int32x4.bitselect === "undefined") { /** - * @param {int32x4} t An instance of int32x4. - * @param {integer} 32-bit value used for x lane. + * @param {int32x4} t Selector mask. An instance of int32x4 + * @param {int32x4} trueValue Pick bit from here if corresponding + * selector bit is 1 + * @param {int32x4} falseValue Pick bit from here if corresponding + * selector bit is 0 + * @return {int32x4} Mix of bits from trueValue or falseValue as + * indicated + */ + SIMD.int32x4.bitselect = function(t, trueValue, falseValue) { + t = SIMD.int32x4(t); + trueValue = SIMD.int32x4(trueValue); + falseValue = SIMD.int32x4(falseValue); + var tr = SIMD.int32x4.and(t, trueValue); + var fr = SIMD.int32x4.and(SIMD.int32x4.not(t), falseValue); + return SIMD.int32x4.or(tr, fr); + } +} + +if (typeof SIMD.int32x4.withX === "undefined") { + /** + * @param {int32x4} t An instance of int32x4. + * @param {integer} 32-bit value used for x lane. * @return {int32x4} New instance of int32x4 with the values in t and * x lane replaced with {x}. */ @@ -2413,7 +2478,7 @@ if (typeof SIMD.int32x4.withX === "undefined") { if (typeof SIMD.int32x4.withY === "undefined") { /** - * param {int32x4} t An instance of int32x4. + * @param {int32x4} t An instance of int32x4. * @param {integer} 32-bit value used for y lane. * @return {int32x4} New instance of int32x4 with the values in t and * y lane replaced with {y}. @@ -2439,6 +2504,7 @@ if (typeof SIMD.int32x4.withZ === "undefined") { if (typeof SIMD.int32x4.withW === "undefined") { /** + * @param {int32x4} t An instance of int32x4. * @param {integer} 32-bit value used for w lane. * @return {int32x4} New instance of int32x4 with the values in t and * w lane replaced with {w}. @@ -2449,67 +2515,11 @@ if (typeof SIMD.int32x4.withW === "undefined") { } } -if (typeof SIMD.int32x4.withFlagX === "undefined") { - /** - * @param {int32x4} t An instance of int32x4. - * @param {boolean} x flag used for x lane. - * @return {int32x4} New instance of int32x4 with the values in t and - * x lane replaced with {x}. - */ - SIMD.int32x4.withFlagX = function(t, flagX) { - t = SIMD.int32x4(t); - var x = flagX ? 0xFFFFFFFF : 0x0; - return SIMD.int32x4(x, t.y, t.z, t.w); - } -} - -if (typeof SIMD.int32x4.withFlagY === "undefined") { - /** - * @param {int32x4} t An instance of int32x4. - * @param {boolean} y flag used for y lane. - * @return {int32x4} New instance of int32x4 with the values in t and - * y lane replaced with {y}. - */ - SIMD.int32x4.withFlagY = function(t, flagY) { - t = SIMD.int32x4(t); - var y = flagY ? 0xFFFFFFFF : 0x0; - return SIMD.int32x4(t.x, y, t.z, t.w); - } -} - -if (typeof SIMD.int32x4.withFlagZ === "undefined") { - /** - * @param {int32x4} t An instance of int32x4. - * @param {boolean} z flag used for z lane. - * @return {int32x4} New instance of int32x4 with the values in t and - * z lane replaced with {z}. - */ - SIMD.int32x4.withFlagZ = function(t, flagZ) { - t = SIMD.int32x4(t); - var z = flagZ ? 0xFFFFFFFF : 0x0; - return SIMD.int32x4(t.x, t.y, z, t.w); - } -} - -if (typeof SIMD.int32x4.withFlagW === "undefined") { - /** - * @param {int32x4} t An instance of int32x4. - * @param {boolean} w flag used for w lane. - * @return {int32x4} New instance of int32x4 with the values in t and - * w lane replaced with {w}. - */ - SIMD.int32x4.withFlagW = function(t, flagW) { - t = SIMD.int32x4(t); - var w = flagW ? 0xFFFFFFFF : 0x0; - return SIMD.int32x4(t.x, t.y, t.z, w); - } -} - if (typeof SIMD.int32x4.equal === "undefined") { /** * @param {int32x4} t An instance of int32x4. * @param {int32x4} other An instance of int32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t == other. */ SIMD.int32x4.equal = function(t, other) { @@ -2527,7 +2537,7 @@ if (typeof SIMD.int32x4.notEqual === "undefined") { /** * @param {int32x4} t An instance of int32x4. * @param {int32x4} other An instance of int32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t != other. */ SIMD.int32x4.notEqual = function(t, other) { @@ -2545,7 +2555,7 @@ if (typeof SIMD.int32x4.greaterThan === "undefined") { /** * @param {int32x4} t An instance of int32x4. * @param {int32x4} other An instance of int32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t > other. */ SIMD.int32x4.greaterThan = function(t, other) { @@ -2563,7 +2573,7 @@ if (typeof SIMD.int32x4.greaterThanOrEqual === "undefined") { /** * @param {int32x4} t An instance of int32x4. * @param {int32x4} other An instance of int32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t >= other. */ SIMD.int32x4.greaterThanOrEqual = function(t, other) { @@ -2581,7 +2591,7 @@ if (typeof SIMD.int32x4.lessThan === "undefined") { /** * @param {int32x4} t An instance of int32x4. * @param {int32x4} other An instance of int32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t < other. */ SIMD.int32x4.lessThan = function(t, other) { @@ -2599,7 +2609,7 @@ if (typeof SIMD.int32x4.lessThanOrEqual === "undefined") { /** * @param {int32x4} t An instance of int32x4. * @param {int32x4} other An instance of int32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on + * @return {int32x4} true or false in each lane depending on * the result of t <= other. */ SIMD.int32x4.lessThanOrEqual = function(t, other) { @@ -2613,82 +2623,10 @@ if (typeof SIMD.int32x4.lessThanOrEqual === "undefined") { } } -if (typeof SIMD.int32x4.unsignedGreaterThan === "undefined") { - /** - * @param {int32x4} t An instance of int32x4. - * @param {int32x4} other An instance of int32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on - * the result of t>>>0 > other>>>0. - */ - SIMD.int32x4.unsignedGreaterThan = function(t, other) { - t = SIMD.int32x4(t); - other = SIMD.int32x4(other); - var cx = t.x>>>0 > other.x>>>0; - var cy = t.y>>>0 > other.y>>>0; - var cz = t.z>>>0 > other.z>>>0; - var cw = t.w>>>0 > other.w>>>0; - return SIMD.int32x4.bool(cx, cy, cz, cw); - } -} - -if (typeof SIMD.int32x4.unsignedGreaterThanOrEqual === "undefined") { - /** - * @param {int32x4} t An instance of int32x4. - * @param {int32x4} other An instance of int32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on - * the result of t>>>0 >= other>>>0. - */ - SIMD.int32x4.unsignedGreaterThanOrEqual = function(t, other) { - t = SIMD.int32x4(t); - other = SIMD.int32x4(other); - var cx = t.x>>>0 >= other.x>>>0; - var cy = t.y>>>0 >= other.y>>>0; - var cz = t.z>>>0 >= other.z>>>0; - var cw = t.w>>>0 >= other.w>>>0; - return SIMD.int32x4.bool(cx, cy, cz, cw); - } -} - -if (typeof SIMD.int32x4.unsignedLessThan === "undefined") { - /** - * @param {int32x4} t An instance of int32x4. - * @param {int32x4} other An instance of int32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on - * the result of t>>>0 < other>>>0. - */ - SIMD.int32x4.unsignedLessThan = function(t, other) { - t = SIMD.int32x4(t); - other = SIMD.int32x4(other); - var cx = t.x>>>0 < other.x>>>0; - var cy = t.y>>>0 < other.y>>>0; - var cz = t.z>>>0 < other.z>>>0; - var cw = t.w>>>0 < other.w>>>0; - return SIMD.int32x4.bool(cx, cy, cz, cw); - } -} - -if (typeof SIMD.int32x4.unsignedLessThanOrEqual === "undefined") { - /** - * @param {int32x4} t An instance of int32x4. - * @param {int32x4} other An instance of int32x4. - * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on - * the result of t>>>0 <= other>>>0. - */ - SIMD.int32x4.unsignedLessThanOrEqual = function(t, other) { - t = SIMD.int32x4(t); - other = SIMD.int32x4(other); - var cx = t.x>>>0 <= other.x>>>0; - var cy = t.y>>>0 <= other.y>>>0; - var cz = t.z>>>0 <= other.z>>>0; - var cw = t.w>>>0 <= other.w>>>0; - return SIMD.int32x4.bool(cx, cy, cz, cw); - } -} - if (typeof SIMD.int32x4.shiftLeftByScalar === "undefined") { /** * @param {int32x4} a An instance of int32x4. - * @param {int} bits Bit count to shift by. + * @param {integer} bits Bit count to shift by. * @return {int32x4} lanes in a shifted by bits. */ SIMD.int32x4.shiftLeftByScalar = function(a, bits) { @@ -2706,7 +2644,7 @@ if (typeof SIMD.int32x4.shiftLeftByScalar === "undefined") { if (typeof SIMD.int32x4.shiftRightLogicalByScalar === "undefined") { /** * @param {int32x4} a An instance of int32x4. - * @param {int} bits Bit count to shift by. + * @param {integer} bits Bit count to shift by. * @return {int32x4} lanes in a shifted by bits. */ SIMD.int32x4.shiftRightLogicalByScalar = function(a, bits) { @@ -2724,7 +2662,7 @@ if (typeof SIMD.int32x4.shiftRightLogicalByScalar === "undefined") { if (typeof SIMD.int32x4.shiftRightArithmeticByScalar === "undefined") { /** * @param {int32x4} a An instance of int32x4. - * @param {int} bits Bit count to shift by. + * @param {integer} bits Bit count to shift by. * @return {int32x4} lanes in a shifted by bits. */ SIMD.int32x4.shiftRightArithmeticByScalar = function(a, bits) { @@ -2739,60 +2677,6 @@ if (typeof SIMD.int32x4.shiftRightArithmeticByScalar === "undefined") { } } -if (typeof SIMD.int32x4.shiftLeft === "undefined") { - /** - * @param {int32x4} a An instance of int32x4. - * @param {int32x4} bits An instance of int32x4. - * @return {int32x4} lanes New instance of int32x4 with values of a shifted - * left by bits. - */ - SIMD.int32x4.shiftLeft = function(a, bits) { - a = SIMD.int32x4(a); - bits = SIMD.int32x4(bits); - var x = bits.x>>>0 >= 32 ? 0 : a.x << bits.x; - var y = bits.y>>>0 >= 32 ? 0 : a.y << bits.y; - var z = bits.z>>>0 >= 32 ? 0 : a.z << bits.z; - var w = bits.w>>>0 >= 32 ? 0 : a.w << bits.w; - return SIMD.int32x4(x, y, z, w); - } -} - -if (typeof SIMD.int32x4.shiftRightLogical === "undefined") { - /** - * @param {int32x4} a An instance of int32x4. - * @param {int32x4} bits An instance of int32x4. - * @return {int32x4} lanes New instance of int32x4 with values of a - * logically-shifted right by bits. - */ - SIMD.int32x4.shiftRightLogical = function(a, bits) { - a = SIMD.int32x4(a); - bits = SIMD.int32x4(bits); - var x = bits.x>>>0 >= 32 ? 0 : a.x >>> bits.x; - var y = bits.y>>>0 >= 32 ? 0 : a.y >>> bits.y; - var z = bits.z>>>0 >= 32 ? 0 : a.z >>> bits.z; - var w = bits.w>>>0 >= 32 ? 0 : a.w >>> bits.w; - return SIMD.int32x4(x, y, z, w); - } -} - -if (typeof SIMD.int32x4.shiftRightArithmetic === "undefined") { - /** - * @param {int32x4} a An instance of int32x4. - * @param {int32x4} bits An instance of int32x4. - * @return {int32x4} lanes New instance of int32x4 with values of a - * arithmetic-shifted right by bits. - */ - SIMD.int32x4.shiftRightArithmetic = function(a, bits) { - a = SIMD.int32x4(a); - bits = SIMD.int32x4(bits); - var x = a.x >> (bits.x>>>0 > 31 ? 31 : bits.x); - var y = a.y >> (bits.y>>>0 > 31 ? 31 : bits.y); - var z = a.z >> (bits.z>>>0 > 31 ? 31 : bits.z); - var w = a.w >> (bits.w>>>0 > 31 ? 31 : bits.w); - return SIMD.int32x4(x, y, z, w); - } -} - if (typeof SIMD.int32x4.load === "undefined") { /** * @param {Typed array} tarray An instance of a typed array. @@ -3137,9 +3021,9 @@ if (typeof SIMD.int16x8.select === "undefined") { /** * @param {int16x8} t Selector mask. An instance of int16x8 * @param {int16x8} trueValue Pick lane from here if corresponding - * selector lane is 0xFFFF + * selector lane is true * @param {int16x8} falseValue Pick lane from here if corresponding - * selector lane is 0x0 + * selector lane is false * @return {int16x8} Mix of lanes from trueValue or falseValue as * indicated */ @@ -3157,7 +3041,7 @@ if (typeof SIMD.int16x8.equal === "undefined") { /** * @param {int16x8} t An instance of int16x8. * @param {int16x8} other An instance of int16x8. - * @return {int16x8} 0xFFFF or 0x0 in each lane depending on + * @return {int16x8} true or false in each lane depending on * the result of t == other. */ SIMD.int16x8.equal = function(t, other) { @@ -3179,7 +3063,7 @@ if (typeof SIMD.int16x8.notEqual === "undefined") { /** * @param {int16x8} t An instance of int16x8. * @param {int16x8} other An instance of int16x8. - * @return {int16x8} 0xFFFF or 0x0 in each lane depending on + * @return {int16x8} true or false in each lane depending on * the result of t != other. */ SIMD.int16x8.notEqual = function(t, other) { @@ -3201,7 +3085,7 @@ if (typeof SIMD.int16x8.greaterThan === "undefined") { /** * @param {int16x8} t An instance of int16x8. * @param {int16x8} other An instance of int16x8. - * @return {int16x8} 0xFFFF or 0x0 in each lane depending on + * @return {int16x8} true or false in each lane depending on * the result of t > other. */ SIMD.int16x8.greaterThan = function(t, other) { @@ -3223,7 +3107,7 @@ if (typeof SIMD.int16x8.greaterThanOrEqual === "undefined") { /** * @param {int16x8} t An instance of int16x8. * @param {int16x8} other An instance of int16x8. - * @return {int16x8} 0xFFFF or 0x0 in each lane depending on + * @return {int16x8} true or false in each lane depending on * the result of t >= other. */ SIMD.int16x8.greaterThanOrEqual = function(t, other) { @@ -3245,7 +3129,7 @@ if (typeof SIMD.int16x8.lessThan === "undefined") { /** * @param {int16x8} t An instance of int16x8. * @param {int16x8} other An instance of int16x8. - * @return {int16x8} 0xFFFF or 0x0 in each lane depending on + * @return {int16x8} true or false in each lane depending on * the result of t < other. */ SIMD.int16x8.lessThan = function(t, other) { @@ -3267,7 +3151,7 @@ if (typeof SIMD.int16x8.lessThanOrEqual === "undefined") { /** * @param {int16x8} t An instance of int16x8. * @param {int16x8} other An instance of int16x8. - * @return {int16x8} 0xFFFF or 0x0 in each lane depending on + * @return {int16x8} true or false in each lane depending on * the result of t <= other. */ SIMD.int16x8.lessThanOrEqual = function(t, other) { @@ -3285,98 +3169,10 @@ if (typeof SIMD.int16x8.lessThanOrEqual === "undefined") { } } -if (typeof SIMD.int16x8.unsignedGreaterThan === "undefined") { - /** - * @param {int16x8} t An instance of int16x8. - * @param {int16x8} other An instance of int16x8. - * @return {int16x8} 0xFFFF or 0x0 in each lane depending on - * the result of t>>>0 > other>>>0. - */ - SIMD.int16x8.unsignedGreaterThan = function(t, other) { - t = SIMD.int16x8(t); - other = SIMD.int16x8(other); - var cs0 = t.s0>>>0 > other.s0>>>0; - var cs1 = t.s1>>>0 > other.s1>>>0; - var cs2 = t.s2>>>0 > other.s2>>>0; - var cs3 = t.s3>>>0 > other.s3>>>0; - var cs4 = t.s4>>>0 > other.s4>>>0; - var cs5 = t.s5>>>0 > other.s5>>>0; - var cs6 = t.s6>>>0 > other.s6>>>0; - var cs7 = t.s7>>>0 > other.s7>>>0; - return SIMD.int16x8.bool(cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7); - } -} - -if (typeof SIMD.int16x8.unsignedGreaterThanOrEqual === "undefined") { - /** - * @param {int16x8} t An instance of int16x8. - * @param {int16x8} other An instance of int16x8. - * @return {int16x8} 0xFFFF or 0x0 in each lane depending on - * the result of t>>>0 >= other>>>0. - */ - SIMD.int16x8.unsignedGreaterThanOrEqual = function(t, other) { - t = SIMD.int16x8(t); - other = SIMD.int16x8(other); - var cs0 = t.s0>>>0 >= other.s0>>>0; - var cs1 = t.s1>>>0 >= other.s1>>>0; - var cs2 = t.s2>>>0 >= other.s2>>>0; - var cs3 = t.s3>>>0 >= other.s3>>>0; - var cs4 = t.s4>>>0 >= other.s4>>>0; - var cs5 = t.s5>>>0 >= other.s5>>>0; - var cs6 = t.s6>>>0 >= other.s6>>>0; - var cs7 = t.s7>>>0 >= other.s7>>>0; - return SIMD.int16x8.bool(cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7); - } -} - -if (typeof SIMD.int16x8.unsignedLessThan === "undefined") { - /** - * @param {int16x8} t An instance of int16x8. - * @param {int16x8} other An instance of int16x8. - * @return {int16x8} 0xFFFF or 0x0 in each lane depending on - * the result of t>>>0 < other>>>0. - */ - SIMD.int16x8.unsignedLessThan = function(t, other) { - t = SIMD.int16x8(t); - other = SIMD.int16x8(other); - var cs0 = t.s0>>>0 < other.s0>>>0; - var cs1 = t.s1>>>0 < other.s1>>>0; - var cs2 = t.s2>>>0 < other.s2>>>0; - var cs3 = t.s3>>>0 < other.s3>>>0; - var cs4 = t.s4>>>0 < other.s4>>>0; - var cs5 = t.s5>>>0 < other.s5>>>0; - var cs6 = t.s6>>>0 < other.s6>>>0; - var cs7 = t.s7>>>0 < other.s7>>>0; - return SIMD.int16x8.bool(cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7); - } -} - -if (typeof SIMD.int16x8.unsignedLessThanOrEqual === "undefined") { - /** - * @param {int16x8} t An instance of int16x8. - * @param {int16x8} other An instance of int16x8. - * @return {int16x8} 0xFFFF or 0x0 in each lane depending on - * the result of t>>>0 <= other>>>0. - */ - SIMD.int16x8.unsignedLessThanOrEqual = function(t, other) { - t = SIMD.int16x8(t); - other = SIMD.int16x8(other); - var cs0 = t.s0>>>0 <= other.s0>>>0; - var cs1 = t.s1>>>0 <= other.s1>>>0; - var cs2 = t.s2>>>0 <= other.s2>>>0; - var cs3 = t.s3>>>0 <= other.s3>>>0; - var cs4 = t.s4>>>0 <= other.s4>>>0; - var cs5 = t.s5>>>0 <= other.s5>>>0; - var cs6 = t.s6>>>0 <= other.s6>>>0; - var cs7 = t.s7>>>0 <= other.s7>>>0; - return SIMD.int16x8.bool(cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7); - } -} - if (typeof SIMD.int16x8.shiftLeftByScalar === "undefined") { /** * @param {int16x8} a An instance of int16x8. - * @param {int} bits Bit count to shift by. + * @param {integer} bits Bit count to shift by. * @return {int16x8} lanes in a shifted by bits. */ SIMD.int16x8.shiftLeftByScalar = function(a, bits) { @@ -3398,7 +3194,7 @@ if (typeof SIMD.int16x8.shiftLeftByScalar === "undefined") { if (typeof SIMD.int16x8.shiftRightLogicalByScalar === "undefined") { /** * @param {int16x8} a An instance of int16x8. - * @param {int} bits Bit count to shift by. + * @param {integer} bits Bit count to shift by. * @return {int16x8} lanes in a shifted by bits. */ SIMD.int16x8.shiftRightLogicalByScalar = function(a, bits) { @@ -3420,7 +3216,7 @@ if (typeof SIMD.int16x8.shiftRightLogicalByScalar === "undefined") { if (typeof SIMD.int16x8.shiftRightArithmeticByScalar === "undefined") { /** * @param {int16x8} a An instance of int16x8. - * @param {int} bits Bit count to shift by. + * @param {integer} bits Bit count to shift by. * @return {int16x8} lanes in a shifted by bits. */ SIMD.int16x8.shiftRightArithmeticByScalar = function(a, bits) { @@ -3439,72 +3235,6 @@ if (typeof SIMD.int16x8.shiftRightArithmeticByScalar === "undefined") { } } -if (typeof SIMD.int16x8.shiftLeft === "undefined") { - /** - * @param {int16x8} a An instance of int16x8. - * @param {int16x8} bits An instance of int16x8. - * @return {int16x8} lanes New instance of int16x8 with values of a shifted - * left by bits. - */ - SIMD.int16x8.shiftLeft = function(a, bits) { - a = SIMD.int16x8(a); - bits = SIMD.int16x8(bits); - var s0 = bits.s0>>>0 >= 32 ? 0 : a.s0 << bits.s0; - var s1 = bits.s1>>>0 >= 32 ? 0 : a.s1 << bits.s1; - var s2 = bits.s2>>>0 >= 32 ? 0 : a.s2 << bits.s2; - var s3 = bits.s3>>>0 >= 32 ? 0 : a.s3 << bits.s3; - var s4 = bits.s4>>>0 >= 32 ? 0 : a.s4 << bits.s4; - var s5 = bits.s5>>>0 >= 32 ? 0 : a.s5 << bits.s5; - var s6 = bits.s6>>>0 >= 32 ? 0 : a.s6 << bits.s6; - var s7 = bits.s7>>>0 >= 32 ? 0 : a.s7 << bits.s7; - return SIMD.int16x8(s0, s1, s2, s3, s4, s5, s6, s7); - } -} - -if (typeof SIMD.int16x8.shiftRightLogical === "undefined") { - /** - * @param {int16x8} a An instance of int16x8. - * @param {int16x8} bits An instance of int16x8. - * @return {int16x8} lanes New instance of int16x8 with values of a - * logically-shifted right by bits. - */ - SIMD.int16x8.shiftRightLogical = function(a, bits) { - a = SIMD.int16x8(a); - bits = SIMD.int16x8(bits); - var s0 = bits.s0>>>0 >= 32 ? 0 : a.s0 >>> bits.s0; - var s1 = bits.s1>>>0 >= 32 ? 0 : a.s1 >>> bits.s1; - var s2 = bits.s2>>>0 >= 32 ? 0 : a.s2 >>> bits.s2; - var s3 = bits.s3>>>0 >= 32 ? 0 : a.s3 >>> bits.s3; - var s4 = bits.s4>>>0 >= 32 ? 0 : a.s4 >>> bits.s4; - var s5 = bits.s5>>>0 >= 32 ? 0 : a.s5 >>> bits.s5; - var s5 = bits.s6>>>0 >= 32 ? 0 : a.s6 >>> bits.s6; - var s6 = bits.s7>>>0 >= 32 ? 0 : a.s7 >>> bits.s7; - return SIMD.int16x8(s0, s1, s2, s3, s4, s5, s6, s7); - } -} - -if (typeof SIMD.int16x8.shiftRightArithmetic === "undefined") { - /** - * @param {int16x8} a An instance of int16x8. - * @param {int16x8} bits An instance of int16x8. - * @return {int16x8} lanes New instance of int16x8 with values of a - * arithmetic-shifted right by bits. - */ - SIMD.int16x8.shiftRightArithmetic = function(a, bits) { - a = SIMD.int16x8(a); - bits = SIMD.int16x8(bits); - var s0 = a.s0 >> (bits.s0>>>0 > 31 ? 31 : bits.s0); - var s1 = a.s1 >> (bits.s1>>>0 > 31 ? 31 : bits.s1); - var s2 = a.s2 >> (bits.s2>>>0 > 31 ? 31 : bits.s2); - var s3 = a.s3 >> (bits.s3>>>0 > 31 ? 31 : bits.s3); - var s4 = a.s4 >> (bits.s4>>>0 > 31 ? 31 : bits.s4); - var s5 = a.s5 >> (bits.s5>>>0 > 31 ? 31 : bits.s5); - var s6 = a.s6 >> (bits.s6>>>0 > 31 ? 31 : bits.s6); - var s7 = a.s7 >> (bits.s7>>>0 > 31 ? 31 : bits.s7); - return SIMD.int16x8(s0, s1, s2, s3, s4, s5, s6, s7); - } -} - if (typeof SIMD.int16x8.load === "undefined") { /** * @param {Typed array} tarray An instance of a typed array. @@ -3566,90 +3296,6 @@ if (typeof SIMD.int16x8.store === "undefined") { } } -if (typeof SIMD.int16x8.saturatingAdd === "undefined") { - /** - * @param {int16x8} a An instance of int16x8. - * @param {int16x8} b An instance of int16x8. - * @return {int16x8} New instance of int16x8 with values of - * Math.max(Math.min(a + b, 32767), -32768). - */ - SIMD.int16x8.saturatingAdd = function(a, b) { - a = SIMD.int16x8(a); - b = SIMD.int16x8(b); - return SIMD.int16x8(Math.max(Math.min(a.s0 + b.s0, 32767), -32768), - Math.max(Math.min(a.s1 + b.s1, 32767), -32768), - Math.max(Math.min(a.s2 + b.s2, 32767), -32768), - Math.max(Math.min(a.s3 + b.s3, 32767), -32768), - Math.max(Math.min(a.s4 + b.s4, 32767), -32768), - Math.max(Math.min(a.s5 + b.s5, 32767), -32768), - Math.max(Math.min(a.s6 + b.s6, 32767), -32768), - Math.max(Math.min(a.s7 + b.s7, 32767), -32768)); - } -} - -if (typeof SIMD.int16x8.saturatingSub === "undefined") { - /** - * @param {int16x8} a An instance of int16x8. - * @param {int16x8} b An instance of int16x8. - * @return {int16x8} New instance of int16x8 with values of - * Math.max(Math.min(a - b, 32767), -32768). - */ - SIMD.int16x8.saturatingSub = function(a, b) { - a = SIMD.int16x8(a); - b = SIMD.int16x8(b); - return SIMD.int16x8(Math.max(Math.min(a.s0 - b.s0, 32767), -32768), - Math.max(Math.min(a.s1 - b.s1, 32767), -32768), - Math.max(Math.min(a.s2 - b.s2, 32767), -32768), - Math.max(Math.min(a.s3 - b.s3, 32767), -32768), - Math.max(Math.min(a.s4 - b.s4, 32767), -32768), - Math.max(Math.min(a.s5 - b.s5, 32767), -32768), - Math.max(Math.min(a.s6 - b.s6, 32767), -32768), - Math.max(Math.min(a.s7 - b.s7, 32767), -32768)); - } -} - -if (typeof SIMD.int16x8.unsignedSaturatingAdd === "undefined") { - /** - * @param {int16x8} a An instance of int16x8. - * @param {int16x8} b An instance of int16x8. - * @return {int16x8} New instance of int16x8 with values of - * Math.max(Math.min(a + b, 65535), 0). - */ - SIMD.int16x8.unsignedSaturatingAdd = function(a, b) { - a = SIMD.int16x8(a); - b = SIMD.int16x8(b); - return SIMD.int16x8(Math.max(Math.min(a.s0 + b.s0, 65535), 0), - Math.max(Math.min(a.s1 + b.s1, 65535), 0), - Math.max(Math.min(a.s2 + b.s2, 65535), 0), - Math.max(Math.min(a.s3 + b.s3, 65535), 0), - Math.max(Math.min(a.s4 + b.s4, 65535), 0), - Math.max(Math.min(a.s5 + b.s5, 65535), 0), - Math.max(Math.min(a.s6 + b.s6, 65535), 0), - Math.max(Math.min(a.s7 + b.s7, 65535), 0)); - } -} - -if (typeof SIMD.int16x8.unsignedSaturatingSub === "undefined") { - /** - * @param {int16x8} a An instance of int16x8. - * @param {int16x8} b An instance of int16x8. - * @return {int16x8} New instance of int16x8 with values of - * Math.max(Math.min(a - b, 65535), 0). - */ - SIMD.int16x8.unsignedSaturatingSub = function(a, b) { - a = SIMD.int16x8(a); - b = SIMD.int16x8(b); - return SIMD.int16x8(Math.max(Math.min(a.s0 - b.s0, 65535), 0), - Math.max(Math.min(a.s1 - b.s1, 65535), 0), - Math.max(Math.min(a.s2 - b.s2, 65535), 0), - Math.max(Math.min(a.s3 - b.s3, 65535), 0), - Math.max(Math.min(a.s4 - b.s4, 65535), 0), - Math.max(Math.min(a.s5 - b.s5, 65535), 0), - Math.max(Math.min(a.s6 - b.s6, 65535), 0), - Math.max(Math.min(a.s7 - b.s7, 65535), 0)); - } -} - if (typeof SIMD.int8x16.and === "undefined") { /** * @param {int8x16} a An instance of int8x16. @@ -3782,9 +3428,9 @@ if (typeof SIMD.int8x16.select === "undefined") { /** * @param {int8x16} t Selector mask. An instance of int8x16 * @param {int8x16} trueValue Pick lane from here if corresponding - * selector lane is 0xFF + * selector lane is true * @param {int8x16} falseValue Pick lane from here if corresponding - * selector lane is 0x0 + * selector lane is false * @return {int8x16} Mix of lanes from trueValue or falseValue as * indicated */ @@ -3802,7 +3448,7 @@ if (typeof SIMD.int8x16.equal === "undefined") { /** * @param {int8x16} t An instance of int8x16. * @param {int8x16} other An instance of int8x16. - * @return {int8x16} 0xFF or 0x0 in each lane depending on + * @return {int8x16} true or false in each lane depending on * the result of t == other. */ SIMD.int8x16.equal = function(t, other) { @@ -3833,7 +3479,7 @@ if (typeof SIMD.int8x16.notEqual === "undefined") { /** * @param {int8x16} t An instance of int8x16. * @param {int8x16} other An instance of int8x16. - * @return {int8x16} 0xFF or 0x0 in each lane depending on + * @return {int8x16} true or false in each lane depending on * the result of t != other. */ SIMD.int8x16.notEqual = function(t, other) { @@ -3864,7 +3510,7 @@ if (typeof SIMD.int8x16.greaterThan === "undefined") { /** * @param {int8x16} t An instance of int8x16. * @param {int8x16} other An instance of int8x16. - * @return {int8x16} 0xFF or 0x0 in each lane depending on + * @return {int8x16} true or false in each lane depending on * the result of t > other. */ SIMD.int8x16.greaterThan = function(t, other) { @@ -3895,7 +3541,7 @@ if (typeof SIMD.int8x16.greaterThanOrEqual === "undefined") { /** * @param {int8x16} t An instance of int8x16. * @param {int8x16} other An instance of int8x16. - * @return {int8x16} 0xFF or 0x0 in each lane depending on + * @return {int8x16} true or false in each lane depending on * the result of t >= other. */ SIMD.int8x16.greaterThanOrEqual = function(t, other) { @@ -3926,7 +3572,7 @@ if (typeof SIMD.int8x16.lessThan === "undefined") { /** * @param {int8x16} t An instance of int8x16. * @param {int8x16} other An instance of int8x16. - * @return {int8x16} 0xFF or 0x0 in each lane depending on + * @return {int8x16} true or false in each lane depending on * the result of t < other. */ SIMD.int8x16.lessThan = function(t, other) { @@ -3957,7 +3603,7 @@ if (typeof SIMD.int8x16.lessThanOrEqual === "undefined") { /** * @param {int8x16} t An instance of int8x16. * @param {int8x16} other An instance of int8x16. - * @return {int8x16} 0xFF or 0x0 in each lane depending on + * @return {int8x16} true or false in each lane depending on * the result of t <= other. */ SIMD.int8x16.lessThanOrEqual = function(t, other) { @@ -3984,134 +3630,10 @@ if (typeof SIMD.int8x16.lessThanOrEqual === "undefined") { } } -if (typeof SIMD.int8x16.unsignedGreaterThan === "undefined") { - /** - * @param {int8x16} t An instance of int8x16. - * @param {int8x16} other An instance of int8x16. - * @return {int8x16} 0xFF or 0x0 in each lane depending on - * the result of t>>>0 > other>>>0. - */ - SIMD.int8x16.unsignedGreaterThan = function(t, other) { - t = SIMD.int8x16(t); - other = SIMD.int8x16(other); - var cs0 = t.s0>>>0 > other.s0>>>0; - var cs1 = t.s1>>>0 > other.s1>>>0; - var cs2 = t.s2>>>0 > other.s2>>>0; - var cs3 = t.s3>>>0 > other.s3>>>0; - var cs4 = t.s4>>>0 > other.s4>>>0; - var cs5 = t.s5>>>0 > other.s5>>>0; - var cs6 = t.s6>>>0 > other.s6>>>0; - var cs7 = t.s7>>>0 > other.s7>>>0; - var cs8 = t.s8>>>0 > other.s8>>>0; - var cs9 = t.s9>>>0 > other.s9>>>0; - var cs10 = t.s10>>>0 > other.s10>>>0; - var cs11 = t.s11>>>0 > other.s11>>>0; - var cs12 = t.s12>>>0 > other.s12>>>0; - var cs13 = t.s13>>>0 > other.s13>>>0; - var cs14 = t.s14>>>0 > other.s14>>>0; - var cs15 = t.s15>>>0 > other.s15>>>0; - return SIMD.int8x16.bool(cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, - cs8, cs9, cs10, cs11, cs12, cs13, cs14, cs15); - } -} - -if (typeof SIMD.int8x16.unsignedGreaterThanOrEqual === "undefined") { - /** - * @param {int8x16} t An instance of int8x16. - * @param {int8x16} other An instance of int8x16. - * @return {int8x16} 0xFF or 0x0 in each lane depending on - * the result of t>>>0 >= other>>>0. - */ - SIMD.int8x16.unsignedGreaterThanOrEqual = function(t, other) { - t = SIMD.int8x16(t); - other = SIMD.int8x16(other); - var cs0 = t.s0>>>0 >= other.s0>>>0; - var cs1 = t.s1>>>0 >= other.s1>>>0; - var cs2 = t.s2>>>0 >= other.s2>>>0; - var cs3 = t.s3>>>0 >= other.s3>>>0; - var cs4 = t.s4>>>0 >= other.s4>>>0; - var cs5 = t.s5>>>0 >= other.s5>>>0; - var cs6 = t.s6>>>0 >= other.s6>>>0; - var cs7 = t.s7>>>0 >= other.s7>>>0; - var cs8 = t.s8>>>0 >= other.s8>>>0; - var cs9 = t.s9>>>0 >= other.s9>>>0; - var cs10 = t.s10>>>0 >= other.s10>>>0; - var cs11 = t.s11>>>0 >= other.s11>>>0; - var cs12 = t.s12>>>0 >= other.s12>>>0; - var cs13 = t.s13>>>0 >= other.s13>>>0; - var cs14 = t.s14>>>0 >= other.s14>>>0; - var cs15 = t.s15>>>0 >= other.s15>>>0; - return SIMD.int8x16.bool(cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, - cs8, cs9, cs10, cs11, cs12, cs13, cs14, cs15); - } -} - -if (typeof SIMD.int8x16.unsignedLessThan === "undefined") { - /** - * @param {int8x16} t An instance of int8x16. - * @param {int8x16} other An instance of int8x16. - * @return {int8x16} 0xFF or 0x0 in each lane depending on - * the result of t>>>0 < other>>>0. - */ - SIMD.int8x16.unsignedLessThan = function(t, other) { - t = SIMD.int8x16(t); - other = SIMD.int8x16(other); - var cs0 = t.s0>>>0 < other.s0>>>0; - var cs1 = t.s1>>>0 < other.s1>>>0; - var cs2 = t.s2>>>0 < other.s2>>>0; - var cs3 = t.s3>>>0 < other.s3>>>0; - var cs4 = t.s4>>>0 < other.s4>>>0; - var cs5 = t.s5>>>0 < other.s5>>>0; - var cs6 = t.s6>>>0 < other.s6>>>0; - var cs7 = t.s7>>>0 < other.s7>>>0; - var cs8 = t.s8>>>0 < other.s8>>>0; - var cs9 = t.s9>>>0 < other.s9>>>0; - var cs10 = t.s10>>>0 < other.s10>>>0; - var cs11 = t.s11>>>0 < other.s11>>>0; - var cs12 = t.s12>>>0 < other.s12>>>0; - var cs13 = t.s13>>>0 < other.s13>>>0; - var cs14 = t.s14>>>0 < other.s14>>>0; - var cs15 = t.s15>>>0 < other.s15>>>0; - return SIMD.int8x16.bool(cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, - cs8, cs9, cs10, cs11, cs12, cs13, cs14, cs15); - } -} - -if (typeof SIMD.int8x16.unsignedLessThanOrEqual === "undefined") { - /** - * @param {int8x16} t An instance of int8x16. - * @param {int8x16} other An instance of int8x16. - * @return {int8x16} 0xFF or 0x0 in each lane depending on - * the result of t>>>0 <= other>>>0. - */ - SIMD.int8x16.unsignedLessThanOrEqual = function(t, other) { - t = SIMD.int8x16(t); - other = SIMD.int8x16(other); - var cs0 = t.s0>>>0 <= other.s0>>>0; - var cs1 = t.s1>>>0 <= other.s1>>>0; - var cs2 = t.s2>>>0 <= other.s2>>>0; - var cs3 = t.s3>>>0 <= other.s3>>>0; - var cs4 = t.s4>>>0 <= other.s4>>>0; - var cs5 = t.s5>>>0 <= other.s5>>>0; - var cs6 = t.s6>>>0 <= other.s6>>>0; - var cs7 = t.s7>>>0 <= other.s7>>>0; - var cs8 = t.s8>>>0 <= other.s8>>>0; - var cs9 = t.s9>>>0 <= other.s9>>>0; - var cs10 = t.s10>>>0 <= other.s10>>>0; - var cs11 = t.s11>>>0 <= other.s11>>>0; - var cs12 = t.s12>>>0 <= other.s12>>>0; - var cs13 = t.s13>>>0 <= other.s13>>>0; - var cs14 = t.s14>>>0 <= other.s14>>>0; - var cs15 = t.s15>>>0 <= other.s15>>>0; - return SIMD.int8x16.bool(cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, - cs8, cs9, cs10, cs11, cs12, cs13, cs14, cs15); - } -} - if (typeof SIMD.int8x16.shiftLeftByScalar === "undefined") { /** * @param {int8x16} a An instance of int8x16. - * @param {int} bits Bit count to shift by. + * @param {integer} bits Bit count to shift by. * @return {int8x16} lanes in a shifted by bits. */ SIMD.int8x16.shiftLeftByScalar = function(a, bits) { @@ -4126,14 +3648,14 @@ if (typeof SIMD.int8x16.shiftLeftByScalar === "undefined") { var s5 = a.s5 << bits; var s6 = a.s6 << bits; var s7 = a.s7 << bits; - var s8 = t.s8 << bits; - var s9 = t.s9 << bits; - var s10 = t.s10 << bits; - var s11 = t.s11 << bits; - var s12 = t.s12 << bits; - var s13 = t.s13 << bits; - var s14 = t.s14 << bits; - var s15 = t.s15 << bits; + var s8 = a.s8 << bits; + var s9 = a.s9 << bits; + var s10 = a.s10 << bits; + var s11 = a.s11 << bits; + var s12 = a.s12 << bits; + var s13 = a.s13 << bits; + var s14 = a.s14 << bits; + var s15 = a.s15 << bits; return SIMD.int8x16(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15); } @@ -4142,7 +3664,7 @@ if (typeof SIMD.int8x16.shiftLeftByScalar === "undefined") { if (typeof SIMD.int8x16.shiftRightLogicalByScalar === "undefined") { /** * @param {int8x16} a An instance of int8x16. - * @param {int} bits Bit count to shift by. + * @param {integer} bits Bit count to shift by. * @return {int8x16} lanes in a shifted by bits. */ SIMD.int8x16.shiftRightLogicalByScalar = function(a, bits) { @@ -4173,7 +3695,7 @@ if (typeof SIMD.int8x16.shiftRightLogicalByScalar === "undefined") { if (typeof SIMD.int8x16.shiftRightArithmeticByScalar === "undefined") { /** * @param {int8x16} a An instance of int8x16. - * @param {int} bits Bit count to shift by. + * @param {integer} bits Bit count to shift by. * @return {int8x16} lanes in a shifted by bits. */ SIMD.int8x16.shiftRightArithmeticByScalar = function(a, bits) { @@ -4201,99 +3723,6 @@ if (typeof SIMD.int8x16.shiftRightArithmeticByScalar === "undefined") { } } -if (typeof SIMD.int8x16.shiftLeft === "undefined") { - /** - * @param {int8x16} a An instance of int8x16. - * @param {int8x16} bits An instance of int8x16. - * @return {int8x16} lanes New instance of int8x16 with values of a shifted - * left by bits. - */ - SIMD.int8x16.shiftLeft = function(a, bits) { - a = SIMD.int8x16(a); - bits = SIMD.int8x16(bits); - var s0 = bits.s0>>>0 >= 32 ? 0 : a.s0 << bits.s0; - var s1 = bits.s1>>>0 >= 32 ? 0 : a.s1 << bits.s1; - var s2 = bits.s2>>>0 >= 32 ? 0 : a.s2 << bits.s2; - var s3 = bits.s3>>>0 >= 32 ? 0 : a.s3 << bits.s3; - var s4 = bits.s4>>>0 >= 32 ? 0 : a.s4 << bits.s4; - var s5 = bits.s5>>>0 >= 32 ? 0 : a.s5 << bits.s5; - var s6 = bits.s6>>>0 >= 32 ? 0 : a.s6 << bits.s6; - var s7 = bits.s7>>>0 >= 32 ? 0 : a.s7 << bits.s7; - var s8 = bits.s8>>>0 >= 32 ? 0 : a.s8 << bits.s8; - var s9 = bits.s9>>>0 >= 32 ? 0 : a.s9 << bits.s9; - var s10 = bits.s10>>>0 >= 32 ? 0 : a.s10 << bits.s10; - var s11 = bits.s11>>>0 >= 32 ? 0 : a.s11 << bits.s11; - var s12 = bits.s12>>>0 >= 32 ? 0 : a.s12 << bits.s12; - var s13 = bits.s13>>>0 >= 32 ? 0 : a.s13 << bits.s13; - var s14 = bits.s14>>>0 >= 32 ? 0 : a.s14 << bits.s14; - var s15 = bits.s15>>>0 >= 32 ? 0 : a.s15 << bits.s15; - return SIMD.int8x16(s0, s1, s2, s3, s4, s5, s6, s7, - s8, s9, s10, s11, s12, s13, s14, s15); - } -} - -if (typeof SIMD.int8x16.shiftRightLogical === "undefined") { - /** - * @param {int8x16} a An instance of int8x16. - * @param {int8x16} bits An instance of int8x16. - * @return {int8x16} lanes New instance of int8x16 with values of a - * logically-shifted right by bits. - */ - SIMD.int8x16.shiftRightLogical = function(a, bits) { - a = SIMD.int8x16(a); - bits = SIMD.int8x16(bits); - var s0 = bits.s0>>>0 >= 32 ? 0 : a.s0 >>> bits.s0; - var s1 = bits.s1>>>0 >= 32 ? 0 : a.s1 >>> bits.s1; - var s2 = bits.s2>>>0 >= 32 ? 0 : a.s2 >>> bits.s2; - var s3 = bits.s3>>>0 >= 32 ? 0 : a.s3 >>> bits.s3; - var s4 = bits.s4>>>0 >= 32 ? 0 : a.s4 >>> bits.s4; - var s5 = bits.s5>>>0 >= 32 ? 0 : a.s5 >>> bits.s5; - var s5 = bits.s6>>>0 >= 32 ? 0 : a.s6 >>> bits.s6; - var s6 = bits.s7>>>0 >= 32 ? 0 : a.s7 >>> bits.s7; - var s8 = bits.s8>>>0 >= 32 ? 0 : a.s8 >>> bits.s8; - var s9 = bits.s9>>>0 >= 32 ? 0 : a.s9 >>> bits.s9; - var s10 = bits.s10>>>0 >= 32 ? 0 : a.s10 >>> bits.s10; - var s11 = bits.s11>>>0 >= 32 ? 0 : a.s11 >>> bits.s11; - var s12 = bits.s12>>>0 >= 32 ? 0 : a.s12 >>> bits.s12; - var s13 = bits.s13>>>0 >= 32 ? 0 : a.s13 >>> bits.s13; - var s14 = bits.s14>>>0 >= 32 ? 0 : a.s14 >>> bits.s14; - var s15 = bits.s15>>>0 >= 32 ? 0 : a.s15 >>> bits.s15; - return SIMD.int8x16(s0, s1, s2, s3, s4, s5, s6, s7, - s8, s9, s10, s11, s12, s13, s14, s15); - } -} - -if (typeof SIMD.int8x16.shiftRightArithmetic === "undefined") { - /** - * @param {int8x16} a An instance of int8x16. - * @param {int8x16} bits An instance of int8x16. - * @return {int8x16} lanes New instance of int8x16 with values of a - * arithmetic-shifted right by bits. - */ - SIMD.int8x16.shiftRightArithmetic = function(a, bits) { - a = SIMD.int8x16(a); - bits = SIMD.int8x16(bits); - var s0 = a.s0 >> (bits.s0>>>0 > 31 ? 31 : bits.s0); - var s1 = a.s1 >> (bits.s1>>>0 > 31 ? 31 : bits.s1); - var s2 = a.s2 >> (bits.s2>>>0 > 31 ? 31 : bits.s2); - var s3 = a.s3 >> (bits.s3>>>0 > 31 ? 31 : bits.s3); - var s4 = a.s4 >> (bits.s4>>>0 > 31 ? 31 : bits.s4); - var s5 = a.s5 >> (bits.s5>>>0 > 31 ? 31 : bits.s5); - var s6 = a.s6 >> (bits.s6>>>0 > 31 ? 31 : bits.s6); - var s7 = a.s7 >> (bits.s7>>>0 > 31 ? 31 : bits.s7); - var s8 = a.s8 >> (bits.s8>>>0 > 31 ? 31 : bits.s8); - var s9 = a.s9 >> (bits.s9>>>0 > 31 ? 31 : bits.s9); - var s10 = a.s10 >> (bits.s10>>>0 > 31 ? 31 : bits.s10); - var s11 = a.s11 >> (bits.s11>>>0 > 31 ? 31 : bits.s11); - var s12 = a.s12 >> (bits.s12>>>0 > 31 ? 31 : bits.s12); - var s13 = a.s13 >> (bits.s13>>>0 > 31 ? 31 : bits.s13); - var s14 = a.s14 >> (bits.s14>>>0 > 31 ? 31 : bits.s14); - var s15 = a.s15 >> (bits.s15>>>0 > 31 ? 31 : bits.s15); - return SIMD.int8x16(s0, s1, s2, s3, s4, s5, s6, s7, - s8, s9, s10, s11, s12, s13, s14, s15); - } -} - if (typeof SIMD.int8x16.load === "undefined") { /** * @param {Typed array} tarray An instance of a typed array. @@ -4308,7 +3737,7 @@ if (typeof SIMD.int8x16.load === "undefined") { var bpe = tarray.BYTES_PER_ELEMENT; if (index < 0 || (index * bpe + 16) > tarray.byteLength) throw new RangeError("The value of index is invalid."); - var i8temp = _SIMD_PRIVATE._i16x8; + var i8temp = _SIMD_PRIVATE._i8x16; var array = bpe == 1 ? i8temp : bpe == 2 ? _SIMD_PRIVATE._i16x8 : bpe == 4 ? (tarray instanceof Float32Array ? _SIMD_PRIVATE._f32x4 : _SIMD_PRIVATE._i32x4) : @@ -4365,499 +3794,353 @@ if (typeof SIMD.int8x16.store === "undefined") { } } -if (typeof SIMD.int8x16.saturatingAdd === "undefined") { - /** - * @param {int8x16} a An instance of int8x16. - * @param {int8x16} b An instance of int8x16. - * @return {int8x16} New instance of int8x16 with values of - * Math.max(Math.min(a + b, 127), -128). - */ - SIMD.int8x16.saturatingAdd = function(a, b) { - a = SIMD.int8x16(a); - b = SIMD.int8x16(b); - return SIMD.int8x16(Math.max(Math.min(a.s0 + b.s0, 127), -128), - Math.max(Math.min(a.s1 + b.s1, 127), -128), - Math.max(Math.min(a.s2 + b.s2, 127), -128), - Math.max(Math.min(a.s3 + b.s3, 127), -128), - Math.max(Math.min(a.s4 + b.s4, 127), -128), - Math.max(Math.min(a.s5 + b.s5, 127), -128), - Math.max(Math.min(a.s6 + b.s6, 127), -128), - Math.max(Math.min(a.s7 + b.s7, 127), -128), - Math.max(Math.min(a.s8 + b.s8, 127), -128), - Math.max(Math.min(a.s9 + b.s9, 127), -128), - Math.max(Math.min(a.s10 + b.s10, 127), -128), - Math.max(Math.min(a.s11 + b.s11, 127), -128), - Math.max(Math.min(a.s12 + b.s12, 127), -128), - Math.max(Math.min(a.s13 + b.s13, 127), -128), - Math.max(Math.min(a.s14 + b.s14, 127), -128), - Math.max(Math.min(a.s15 + b.s15, 127), -128)); - } -} - -if (typeof SIMD.int8x16.saturatingSub === "undefined") { - /** - * @param {int8x16} a An instance of int8x16. - * @param {int8x16} b An instance of int8x16. - * @return {int8x16} New instance of int8x16 with values of - * Math.max(Math.min(a - b, 127), -128). - */ - SIMD.int8x16.saturatingSub = function(a, b) { - a = SIMD.int8x16(a); - b = SIMD.int8x16(b); - return SIMD.int8x16(Math.max(Math.min(a.s0 - b.s0, 127), -128), - Math.max(Math.min(a.s1 - b.s1, 127), -128), - Math.max(Math.min(a.s2 - b.s2, 127), -128), - Math.max(Math.min(a.s3 - b.s3, 127), -128), - Math.max(Math.min(a.s4 - b.s4, 127), -128), - Math.max(Math.min(a.s5 - b.s5, 127), -128), - Math.max(Math.min(a.s6 - b.s6, 127), -128), - Math.max(Math.min(a.s7 - b.s7, 127), -128), - Math.max(Math.min(a.s8 - b.s8, 127), -128), - Math.max(Math.min(a.s9 - b.s9, 127), -128), - Math.max(Math.min(a.s10 - b.s10, 127), -128), - Math.max(Math.min(a.s11 - b.s11, 127), -128), - Math.max(Math.min(a.s12 - b.s12, 127), -128), - Math.max(Math.min(a.s13 - b.s13, 127), -128), - Math.max(Math.min(a.s14 - b.s14, 127), -128), - Math.max(Math.min(a.s15 - b.s15, 127), -128)); - } -} - -if (typeof SIMD.int8x16.unsignedSaturatingAdd === "undefined") { - /** - * @param {int8x16} a An instance of int8x16. - * @param {int8x16} b An instance of int8x16. - * @return {int8x16} New instance of int8x16 with values of - * Math.max(Math.min(a + b, 255), 0). - */ - SIMD.int8x16.unsignedSaturatingAdd = function(a, b) { - a = SIMD.int8x16(a); - b = SIMD.int8x16(b); - return SIMD.int8x16(Math.max(Math.min(a.s0 + b.s0, 255), 0), - Math.max(Math.min(a.s1 + b.s1, 255), 0), - Math.max(Math.min(a.s2 + b.s2, 255), 0), - Math.max(Math.min(a.s3 + b.s3, 255), 0), - Math.max(Math.min(a.s4 + b.s4, 255), 0), - Math.max(Math.min(a.s5 + b.s5, 255), 0), - Math.max(Math.min(a.s6 + b.s6, 255), 0), - Math.max(Math.min(a.s7 + b.s7, 255), 0), - Math.max(Math.min(a.s8 + b.s8, 255), 0), - Math.max(Math.min(a.s9 + b.s9, 255), 0), - Math.max(Math.min(a.s10 + b.s10, 255), 0), - Math.max(Math.min(a.s11 + b.s11, 255), 0), - Math.max(Math.min(a.s12 + b.s12, 255), 0), - Math.max(Math.min(a.s13 + b.s13, 255), 0), - Math.max(Math.min(a.s14 + b.s14, 255), 0), - Math.max(Math.min(a.s15 + b.s15, 255), 0)); - } -} - -if (typeof SIMD.int8x16.unsignedSaturatingSub === "undefined") { - /** - * @param {int8x16} a An instance of int8x16. - * @param {int8x16} b An instance of int8x16. - * @return {int8x16} New instance of int8x16 with values of - * Math.max(Math.min(a - b, 255), 0). - */ - SIMD.int8x16.unsignedSaturatingSub = function(a, b) { - a = SIMD.int8x16(a); - b = SIMD.int8x16(b); - return SIMD.int8x16(Math.max(Math.min(a.s0 - b.s0, 255), 0), - Math.max(Math.min(a.s1 - b.s1, 255), 0), - Math.max(Math.min(a.s2 - b.s2, 255), 0), - Math.max(Math.min(a.s3 - b.s3, 255), 0), - Math.max(Math.min(a.s4 - b.s4, 255), 0), - Math.max(Math.min(a.s5 - b.s5, 255), 0), - Math.max(Math.min(a.s6 - b.s6, 255), 0), - Math.max(Math.min(a.s7 - b.s7, 255), 0), - Math.max(Math.min(a.s8 - b.s8, 255), 0), - Math.max(Math.min(a.s9 - b.s9, 255), 0), - Math.max(Math.min(a.s10 - b.s10, 255), 0), - Math.max(Math.min(a.s11 - b.s11, 255), 0), - Math.max(Math.min(a.s12 - b.s12, 255), 0), - Math.max(Math.min(a.s13 - b.s13, 255), 0), - Math.max(Math.min(a.s14 - b.s14, 255), 0), - Math.max(Math.min(a.s15 - b.s15, 255), 0)); - } -} - -if (typeof SIMD.XXXX === "undefined") { - // Swizzle Masks. - Object.defineProperty(SIMD, 'XXXX', { get: function() { return 0x00; } }); - Object.defineProperty(SIMD, 'XXXY', { get: function() { return 0x40; } }); - Object.defineProperty(SIMD, 'XXXZ', { get: function() { return 0x80; } }); - Object.defineProperty(SIMD, 'XXXW', { get: function() { return 0xC0; } }); - Object.defineProperty(SIMD, 'XXYX', { get: function() { return 0x10; } }); - Object.defineProperty(SIMD, 'XXYY', { get: function() { return 0x50; } }); - Object.defineProperty(SIMD, 'XXYZ', { get: function() { return 0x90; } }); - Object.defineProperty(SIMD, 'XXYW', { get: function() { return 0xD0; } }); - Object.defineProperty(SIMD, 'XXZX', { get: function() { return 0x20; } }); - Object.defineProperty(SIMD, 'XXZY', { get: function() { return 0x60; } }); - Object.defineProperty(SIMD, 'XXZZ', { get: function() { return 0xA0; } }); - Object.defineProperty(SIMD, 'XXZW', { get: function() { return 0xE0; } }); - Object.defineProperty(SIMD, 'XXWX', { get: function() { return 0x30; } }); - Object.defineProperty(SIMD, 'XXWY', { get: function() { return 0x70; } }); - Object.defineProperty(SIMD, 'XXWZ', { get: function() { return 0xB0; } }); - Object.defineProperty(SIMD, 'XXWW', { get: function() { return 0xF0; } }); - Object.defineProperty(SIMD, 'XYXX', { get: function() { return 0x04; } }); - Object.defineProperty(SIMD, 'XYXY', { get: function() { return 0x44; } }); - Object.defineProperty(SIMD, 'XYXZ', { get: function() { return 0x84; } }); - Object.defineProperty(SIMD, 'XYXW', { get: function() { return 0xC4; } }); - Object.defineProperty(SIMD, 'XYYX', { get: function() { return 0x14; } }); - Object.defineProperty(SIMD, 'XYYY', { get: function() { return 0x54; } }); - Object.defineProperty(SIMD, 'XYYZ', { get: function() { return 0x94; } }); - Object.defineProperty(SIMD, 'XYYW', { get: function() { return 0xD4; } }); - Object.defineProperty(SIMD, 'XYZX', { get: function() { return 0x24; } }); - Object.defineProperty(SIMD, 'XYZY', { get: function() { return 0x64; } }); - Object.defineProperty(SIMD, 'XYZZ', { get: function() { return 0xA4; } }); - Object.defineProperty(SIMD, 'XYZW', { get: function() { return 0xE4; } }); - Object.defineProperty(SIMD, 'XYWX', { get: function() { return 0x34; } }); - Object.defineProperty(SIMD, 'XYWY', { get: function() { return 0x74; } }); - Object.defineProperty(SIMD, 'XYWZ', { get: function() { return 0xB4; } }); - Object.defineProperty(SIMD, 'XYWW', { get: function() { return 0xF4; } }); - Object.defineProperty(SIMD, 'XZXX', { get: function() { return 0x08; } }); - Object.defineProperty(SIMD, 'XZXY', { get: function() { return 0x48; } }); - Object.defineProperty(SIMD, 'XZXZ', { get: function() { return 0x88; } }); - Object.defineProperty(SIMD, 'XZXW', { get: function() { return 0xC8; } }); - Object.defineProperty(SIMD, 'XZYX', { get: function() { return 0x18; } }); - Object.defineProperty(SIMD, 'XZYY', { get: function() { return 0x58; } }); - Object.defineProperty(SIMD, 'XZYZ', { get: function() { return 0x98; } }); - Object.defineProperty(SIMD, 'XZYW', { get: function() { return 0xD8; } }); - Object.defineProperty(SIMD, 'XZZX', { get: function() { return 0x28; } }); - Object.defineProperty(SIMD, 'XZZY', { get: function() { return 0x68; } }); - Object.defineProperty(SIMD, 'XZZZ', { get: function() { return 0xA8; } }); - Object.defineProperty(SIMD, 'XZZW', { get: function() { return 0xE8; } }); - Object.defineProperty(SIMD, 'XZWX', { get: function() { return 0x38; } }); - Object.defineProperty(SIMD, 'XZWY', { get: function() { return 0x78; } }); - Object.defineProperty(SIMD, 'XZWZ', { get: function() { return 0xB8; } }); - Object.defineProperty(SIMD, 'XZWW', { get: function() { return 0xF8; } }); - Object.defineProperty(SIMD, 'XWXX', { get: function() { return 0x0C; } }); - Object.defineProperty(SIMD, 'XWXY', { get: function() { return 0x4C; } }); - Object.defineProperty(SIMD, 'XWXZ', { get: function() { return 0x8C; } }); - Object.defineProperty(SIMD, 'XWXW', { get: function() { return 0xCC; } }); - Object.defineProperty(SIMD, 'XWYX', { get: function() { return 0x1C; } }); - Object.defineProperty(SIMD, 'XWYY', { get: function() { return 0x5C; } }); - Object.defineProperty(SIMD, 'XWYZ', { get: function() { return 0x9C; } }); - Object.defineProperty(SIMD, 'XWYW', { get: function() { return 0xDC; } }); - Object.defineProperty(SIMD, 'XWZX', { get: function() { return 0x2C; } }); - Object.defineProperty(SIMD, 'XWZY', { get: function() { return 0x6C; } }); - Object.defineProperty(SIMD, 'XWZZ', { get: function() { return 0xAC; } }); - Object.defineProperty(SIMD, 'XWZW', { get: function() { return 0xEC; } }); - Object.defineProperty(SIMD, 'XWWX', { get: function() { return 0x3C; } }); - Object.defineProperty(SIMD, 'XWWY', { get: function() { return 0x7C; } }); - Object.defineProperty(SIMD, 'XWWZ', { get: function() { return 0xBC; } }); - Object.defineProperty(SIMD, 'XWWW', { get: function() { return 0xFC; } }); - Object.defineProperty(SIMD, 'YXXX', { get: function() { return 0x01; } }); - Object.defineProperty(SIMD, 'YXXY', { get: function() { return 0x41; } }); - Object.defineProperty(SIMD, 'YXXZ', { get: function() { return 0x81; } }); - Object.defineProperty(SIMD, 'YXXW', { get: function() { return 0xC1; } }); - Object.defineProperty(SIMD, 'YXYX', { get: function() { return 0x11; } }); - Object.defineProperty(SIMD, 'YXYY', { get: function() { return 0x51; } }); - Object.defineProperty(SIMD, 'YXYZ', { get: function() { return 0x91; } }); - Object.defineProperty(SIMD, 'YXYW', { get: function() { return 0xD1; } }); - Object.defineProperty(SIMD, 'YXZX', { get: function() { return 0x21; } }); - Object.defineProperty(SIMD, 'YXZY', { get: function() { return 0x61; } }); - Object.defineProperty(SIMD, 'YXZZ', { get: function() { return 0xA1; } }); - Object.defineProperty(SIMD, 'YXZW', { get: function() { return 0xE1; } }); - Object.defineProperty(SIMD, 'YXWX', { get: function() { return 0x31; } }); - Object.defineProperty(SIMD, 'YXWY', { get: function() { return 0x71; } }); - Object.defineProperty(SIMD, 'YXWZ', { get: function() { return 0xB1; } }); - Object.defineProperty(SIMD, 'YXWW', { get: function() { return 0xF1; } }); - Object.defineProperty(SIMD, 'YYXX', { get: function() { return 0x05; } }); - Object.defineProperty(SIMD, 'YYXY', { get: function() { return 0x45; } }); - Object.defineProperty(SIMD, 'YYXZ', { get: function() { return 0x85; } }); - Object.defineProperty(SIMD, 'YYXW', { get: function() { return 0xC5; } }); - Object.defineProperty(SIMD, 'YYYX', { get: function() { return 0x15; } }); - Object.defineProperty(SIMD, 'YYYY', { get: function() { return 0x55; } }); - Object.defineProperty(SIMD, 'YYYZ', { get: function() { return 0x95; } }); - Object.defineProperty(SIMD, 'YYYW', { get: function() { return 0xD5; } }); - Object.defineProperty(SIMD, 'YYZX', { get: function() { return 0x25; } }); - Object.defineProperty(SIMD, 'YYZY', { get: function() { return 0x65; } }); - Object.defineProperty(SIMD, 'YYZZ', { get: function() { return 0xA5; } }); - Object.defineProperty(SIMD, 'YYZW', { get: function() { return 0xE5; } }); - Object.defineProperty(SIMD, 'YYWX', { get: function() { return 0x35; } }); - Object.defineProperty(SIMD, 'YYWY', { get: function() { return 0x75; } }); - Object.defineProperty(SIMD, 'YYWZ', { get: function() { return 0xB5; } }); - Object.defineProperty(SIMD, 'YYWW', { get: function() { return 0xF5; } }); - Object.defineProperty(SIMD, 'YZXX', { get: function() { return 0x09; } }); - Object.defineProperty(SIMD, 'YZXY', { get: function() { return 0x49; } }); - Object.defineProperty(SIMD, 'YZXZ', { get: function() { return 0x89; } }); - Object.defineProperty(SIMD, 'YZXW', { get: function() { return 0xC9; } }); - Object.defineProperty(SIMD, 'YZYX', { get: function() { return 0x19; } }); - Object.defineProperty(SIMD, 'YZYY', { get: function() { return 0x59; } }); - Object.defineProperty(SIMD, 'YZYZ', { get: function() { return 0x99; } }); - Object.defineProperty(SIMD, 'YZYW', { get: function() { return 0xD9; } }); - Object.defineProperty(SIMD, 'YZZX', { get: function() { return 0x29; } }); - Object.defineProperty(SIMD, 'YZZY', { get: function() { return 0x69; } }); - Object.defineProperty(SIMD, 'YZZZ', { get: function() { return 0xA9; } }); - Object.defineProperty(SIMD, 'YZZW', { get: function() { return 0xE9; } }); - Object.defineProperty(SIMD, 'YZWX', { get: function() { return 0x39; } }); - Object.defineProperty(SIMD, 'YZWY', { get: function() { return 0x79; } }); - Object.defineProperty(SIMD, 'YZWZ', { get: function() { return 0xB9; } }); - Object.defineProperty(SIMD, 'YZWW', { get: function() { return 0xF9; } }); - Object.defineProperty(SIMD, 'YWXX', { get: function() { return 0x0D; } }); - Object.defineProperty(SIMD, 'YWXY', { get: function() { return 0x4D; } }); - Object.defineProperty(SIMD, 'YWXZ', { get: function() { return 0x8D; } }); - Object.defineProperty(SIMD, 'YWXW', { get: function() { return 0xCD; } }); - Object.defineProperty(SIMD, 'YWYX', { get: function() { return 0x1D; } }); - Object.defineProperty(SIMD, 'YWYY', { get: function() { return 0x5D; } }); - Object.defineProperty(SIMD, 'YWYZ', { get: function() { return 0x9D; } }); - Object.defineProperty(SIMD, 'YWYW', { get: function() { return 0xDD; } }); - Object.defineProperty(SIMD, 'YWZX', { get: function() { return 0x2D; } }); - Object.defineProperty(SIMD, 'YWZY', { get: function() { return 0x6D; } }); - Object.defineProperty(SIMD, 'YWZZ', { get: function() { return 0xAD; } }); - Object.defineProperty(SIMD, 'YWZW', { get: function() { return 0xED; } }); - Object.defineProperty(SIMD, 'YWWX', { get: function() { return 0x3D; } }); - Object.defineProperty(SIMD, 'YWWY', { get: function() { return 0x7D; } }); - Object.defineProperty(SIMD, 'YWWZ', { get: function() { return 0xBD; } }); - Object.defineProperty(SIMD, 'YWWW', { get: function() { return 0xFD; } }); - Object.defineProperty(SIMD, 'ZXXX', { get: function() { return 0x02; } }); - Object.defineProperty(SIMD, 'ZXXY', { get: function() { return 0x42; } }); - Object.defineProperty(SIMD, 'ZXXZ', { get: function() { return 0x82; } }); - Object.defineProperty(SIMD, 'ZXXW', { get: function() { return 0xC2; } }); - Object.defineProperty(SIMD, 'ZXYX', { get: function() { return 0x12; } }); - Object.defineProperty(SIMD, 'ZXYY', { get: function() { return 0x52; } }); - Object.defineProperty(SIMD, 'ZXYZ', { get: function() { return 0x92; } }); - Object.defineProperty(SIMD, 'ZXYW', { get: function() { return 0xD2; } }); - Object.defineProperty(SIMD, 'ZXZX', { get: function() { return 0x22; } }); - Object.defineProperty(SIMD, 'ZXZY', { get: function() { return 0x62; } }); - Object.defineProperty(SIMD, 'ZXZZ', { get: function() { return 0xA2; } }); - Object.defineProperty(SIMD, 'ZXZW', { get: function() { return 0xE2; } }); - Object.defineProperty(SIMD, 'ZXWX', { get: function() { return 0x32; } }); - Object.defineProperty(SIMD, 'ZXWY', { get: function() { return 0x72; } }); - Object.defineProperty(SIMD, 'ZXWZ', { get: function() { return 0xB2; } }); - Object.defineProperty(SIMD, 'ZXWW', { get: function() { return 0xF2; } }); - Object.defineProperty(SIMD, 'ZYXX', { get: function() { return 0x06; } }); - Object.defineProperty(SIMD, 'ZYXY', { get: function() { return 0x46; } }); - Object.defineProperty(SIMD, 'ZYXZ', { get: function() { return 0x86; } }); - Object.defineProperty(SIMD, 'ZYXW', { get: function() { return 0xC6; } }); - Object.defineProperty(SIMD, 'ZYYX', { get: function() { return 0x16; } }); - Object.defineProperty(SIMD, 'ZYYY', { get: function() { return 0x56; } }); - Object.defineProperty(SIMD, 'ZYYZ', { get: function() { return 0x96; } }); - Object.defineProperty(SIMD, 'ZYYW', { get: function() { return 0xD6; } }); - Object.defineProperty(SIMD, 'ZYZX', { get: function() { return 0x26; } }); - Object.defineProperty(SIMD, 'ZYZY', { get: function() { return 0x66; } }); - Object.defineProperty(SIMD, 'ZYZZ', { get: function() { return 0xA6; } }); - Object.defineProperty(SIMD, 'ZYZW', { get: function() { return 0xE6; } }); - Object.defineProperty(SIMD, 'ZYWX', { get: function() { return 0x36; } }); - Object.defineProperty(SIMD, 'ZYWY', { get: function() { return 0x76; } }); - Object.defineProperty(SIMD, 'ZYWZ', { get: function() { return 0xB6; } }); - Object.defineProperty(SIMD, 'ZYWW', { get: function() { return 0xF6; } }); - Object.defineProperty(SIMD, 'ZZXX', { get: function() { return 0x0A; } }); - Object.defineProperty(SIMD, 'ZZXY', { get: function() { return 0x4A; } }); - Object.defineProperty(SIMD, 'ZZXZ', { get: function() { return 0x8A; } }); - Object.defineProperty(SIMD, 'ZZXW', { get: function() { return 0xCA; } }); - Object.defineProperty(SIMD, 'ZZYX', { get: function() { return 0x1A; } }); - Object.defineProperty(SIMD, 'ZZYY', { get: function() { return 0x5A; } }); - Object.defineProperty(SIMD, 'ZZYZ', { get: function() { return 0x9A; } }); - Object.defineProperty(SIMD, 'ZZYW', { get: function() { return 0xDA; } }); - Object.defineProperty(SIMD, 'ZZZX', { get: function() { return 0x2A; } }); - Object.defineProperty(SIMD, 'ZZZY', { get: function() { return 0x6A; } }); - Object.defineProperty(SIMD, 'ZZZZ', { get: function() { return 0xAA; } }); - Object.defineProperty(SIMD, 'ZZZW', { get: function() { return 0xEA; } }); - Object.defineProperty(SIMD, 'ZZWX', { get: function() { return 0x3A; } }); - Object.defineProperty(SIMD, 'ZZWY', { get: function() { return 0x7A; } }); - Object.defineProperty(SIMD, 'ZZWZ', { get: function() { return 0xBA; } }); - Object.defineProperty(SIMD, 'ZZWW', { get: function() { return 0xFA; } }); - Object.defineProperty(SIMD, 'ZWXX', { get: function() { return 0x0E; } }); - Object.defineProperty(SIMD, 'ZWXY', { get: function() { return 0x4E; } }); - Object.defineProperty(SIMD, 'ZWXZ', { get: function() { return 0x8E; } }); - Object.defineProperty(SIMD, 'ZWXW', { get: function() { return 0xCE; } }); - Object.defineProperty(SIMD, 'ZWYX', { get: function() { return 0x1E; } }); - Object.defineProperty(SIMD, 'ZWYY', { get: function() { return 0x5E; } }); - Object.defineProperty(SIMD, 'ZWYZ', { get: function() { return 0x9E; } }); - Object.defineProperty(SIMD, 'ZWYW', { get: function() { return 0xDE; } }); - Object.defineProperty(SIMD, 'ZWZX', { get: function() { return 0x2E; } }); - Object.defineProperty(SIMD, 'ZWZY', { get: function() { return 0x6E; } }); - Object.defineProperty(SIMD, 'ZWZZ', { get: function() { return 0xAE; } }); - Object.defineProperty(SIMD, 'ZWZW', { get: function() { return 0xEE; } }); - Object.defineProperty(SIMD, 'ZWWX', { get: function() { return 0x3E; } }); - Object.defineProperty(SIMD, 'ZWWY', { get: function() { return 0x7E; } }); - Object.defineProperty(SIMD, 'ZWWZ', { get: function() { return 0xBE; } }); - Object.defineProperty(SIMD, 'ZWWW', { get: function() { return 0xFE; } }); - Object.defineProperty(SIMD, 'WXXX', { get: function() { return 0x03; } }); - Object.defineProperty(SIMD, 'WXXY', { get: function() { return 0x43; } }); - Object.defineProperty(SIMD, 'WXXZ', { get: function() { return 0x83; } }); - Object.defineProperty(SIMD, 'WXXW', { get: function() { return 0xC3; } }); - Object.defineProperty(SIMD, 'WXYX', { get: function() { return 0x13; } }); - Object.defineProperty(SIMD, 'WXYY', { get: function() { return 0x53; } }); - Object.defineProperty(SIMD, 'WXYZ', { get: function() { return 0x93; } }); - Object.defineProperty(SIMD, 'WXYW', { get: function() { return 0xD3; } }); - Object.defineProperty(SIMD, 'WXZX', { get: function() { return 0x23; } }); - Object.defineProperty(SIMD, 'WXZY', { get: function() { return 0x63; } }); - Object.defineProperty(SIMD, 'WXZZ', { get: function() { return 0xA3; } }); - Object.defineProperty(SIMD, 'WXZW', { get: function() { return 0xE3; } }); - Object.defineProperty(SIMD, 'WXWX', { get: function() { return 0x33; } }); - Object.defineProperty(SIMD, 'WXWY', { get: function() { return 0x73; } }); - Object.defineProperty(SIMD, 'WXWZ', { get: function() { return 0xB3; } }); - Object.defineProperty(SIMD, 'WXWW', { get: function() { return 0xF3; } }); - Object.defineProperty(SIMD, 'WYXX', { get: function() { return 0x07; } }); - Object.defineProperty(SIMD, 'WYXY', { get: function() { return 0x47; } }); - Object.defineProperty(SIMD, 'WYXZ', { get: function() { return 0x87; } }); - Object.defineProperty(SIMD, 'WYXW', { get: function() { return 0xC7; } }); - Object.defineProperty(SIMD, 'WYYX', { get: function() { return 0x17; } }); - Object.defineProperty(SIMD, 'WYYY', { get: function() { return 0x57; } }); - Object.defineProperty(SIMD, 'WYYZ', { get: function() { return 0x97; } }); - Object.defineProperty(SIMD, 'WYYW', { get: function() { return 0xD7; } }); - Object.defineProperty(SIMD, 'WYZX', { get: function() { return 0x27; } }); - Object.defineProperty(SIMD, 'WYZY', { get: function() { return 0x67; } }); - Object.defineProperty(SIMD, 'WYZZ', { get: function() { return 0xA7; } }); - Object.defineProperty(SIMD, 'WYZW', { get: function() { return 0xE7; } }); - Object.defineProperty(SIMD, 'WYWX', { get: function() { return 0x37; } }); - Object.defineProperty(SIMD, 'WYWY', { get: function() { return 0x77; } }); - Object.defineProperty(SIMD, 'WYWZ', { get: function() { return 0xB7; } }); - Object.defineProperty(SIMD, 'WYWW', { get: function() { return 0xF7; } }); - Object.defineProperty(SIMD, 'WZXX', { get: function() { return 0x0B; } }); - Object.defineProperty(SIMD, 'WZXY', { get: function() { return 0x4B; } }); - Object.defineProperty(SIMD, 'WZXZ', { get: function() { return 0x8B; } }); - Object.defineProperty(SIMD, 'WZXW', { get: function() { return 0xCB; } }); - Object.defineProperty(SIMD, 'WZYX', { get: function() { return 0x1B; } }); - Object.defineProperty(SIMD, 'WZYY', { get: function() { return 0x5B; } }); - Object.defineProperty(SIMD, 'WZYZ', { get: function() { return 0x9B; } }); - Object.defineProperty(SIMD, 'WZYW', { get: function() { return 0xDB; } }); - Object.defineProperty(SIMD, 'WZZX', { get: function() { return 0x2B; } }); - Object.defineProperty(SIMD, 'WZZY', { get: function() { return 0x6B; } }); - Object.defineProperty(SIMD, 'WZZZ', { get: function() { return 0xAB; } }); - Object.defineProperty(SIMD, 'WZZW', { get: function() { return 0xEB; } }); - Object.defineProperty(SIMD, 'WZWX', { get: function() { return 0x3B; } }); - Object.defineProperty(SIMD, 'WZWY', { get: function() { return 0x7B; } }); - Object.defineProperty(SIMD, 'WZWZ', { get: function() { return 0xBB; } }); - Object.defineProperty(SIMD, 'WZWW', { get: function() { return 0xFB; } }); - Object.defineProperty(SIMD, 'WWXX', { get: function() { return 0x0F; } }); - Object.defineProperty(SIMD, 'WWXY', { get: function() { return 0x4F; } }); - Object.defineProperty(SIMD, 'WWXZ', { get: function() { return 0x8F; } }); - Object.defineProperty(SIMD, 'WWXW', { get: function() { return 0xCF; } }); - Object.defineProperty(SIMD, 'WWYX', { get: function() { return 0x1F; } }); - Object.defineProperty(SIMD, 'WWYY', { get: function() { return 0x5F; } }); - Object.defineProperty(SIMD, 'WWYZ', { get: function() { return 0x9F; } }); - Object.defineProperty(SIMD, 'WWYW', { get: function() { return 0xDF; } }); - Object.defineProperty(SIMD, 'WWZX', { get: function() { return 0x2F; } }); - Object.defineProperty(SIMD, 'WWZY', { get: function() { return 0x6F; } }); - Object.defineProperty(SIMD, 'WWZZ', { get: function() { return 0xAF; } }); - Object.defineProperty(SIMD, 'WWZW', { get: function() { return 0xEF; } }); - Object.defineProperty(SIMD, 'WWWX', { get: function() { return 0x3F; } }); - Object.defineProperty(SIMD, 'WWWY', { get: function() { return 0x7F; } }); - Object.defineProperty(SIMD, 'WWWZ', { get: function() { return 0xBF; } }); - Object.defineProperty(SIMD, 'WWWW', { get: function() { return 0xFF; } }); -} - -if (typeof SIMD.XX === "undefined") { - // Swizzle Masks. - Object.defineProperty(SIMD, 'XX', { get: function() { return 0x0; } }); - Object.defineProperty(SIMD, 'XY', { get: function() { return 0x2; } }); - Object.defineProperty(SIMD, 'YX', { get: function() { return 0x1; } }); - Object.defineProperty(SIMD, 'YY', { get: function() { return 0x3; } }); -} - -// TODO: Profile signMaskPolyfill to avoid conflicting with the builtin signMask, -// which isn't completely functional yet. -if (typeof SIMD.float32x4.signMaskPolyfill === "undefined") { - /** - * Extract the sign bit from each lane return them in the first 4 bits. - */ - Object.defineProperty(SIMD.float32x4.prototype, 'signMaskPolyfill', { - get: function() { - var mx = (this.x < 0.0 || 1/this.x === -Infinity) ? 1 : 0; - var my = (this.y < 0.0 || 1/this.y === -Infinity) ? 1 : 0; - var mz = (this.z < 0.0 || 1/this.z === -Infinity) ? 1 : 0; - var mw = (this.w < 0.0 || 1/this.w === -Infinity) ? 1 : 0; - return mx | my << 1 | mz << 2 | mw << 3; +if (typeof Float32x4Array === "undefined") { + Float32x4Array = function(a, b, c) { + if (_SIMD_PRIVATE.isNumber(a)) { + this.storage_ = new Float32Array(a*4); + this.length_ = a; + this.byteOffset_ = 0; + return; + } else if (_SIMD_PRIVATE.isTypedArray(a)) { + if (!(a instanceof Float32x4Array)) { + throw "Copying typed array of non-Float32x4Array is unimplemented."; + } + this.storage_ = new Float32Array(a.length * 4); + this.length_ = a.length; + this.byteOffset_ = 0; + // Copy floats. + for (var i = 0; i < a.length*4; i++) { + this.storage_[i] = a.storage_[i]; + } + } else if (_SIMD_PRIVATE.isArrayBuffer(a)) { + if ((b != undefined) && (b % Float32x4Array.BYTES_PER_ELEMENT) != 0) { + throw "byteOffset must be a multiple of 16."; + } + if (c != undefined) { + c *= 4; + this.storage_ = new Float32Array(a, b, c); + } + else { + // Note: new Float32Array(a, b) is NOT equivalent to new Float32Array(a, b, undefined) + this.storage_ = new Float32Array(a, b); + } + this.length_ = this.storage_.length / 4; + this.byteOffset_ = b != undefined ? b : 0; + } else { + throw "Unknown type of first argument."; } + } + + Object.defineProperty(Float32x4Array.prototype, 'length', { + get: function() { return this.length_; } }); -} -if (typeof SIMD.float64x2.signMaskPolyfill === "undefined") { - /** - * Extract the sign bit from each lane return them in the first 2 bits. - */ - Object.defineProperty(SIMD.float64x2.prototype, 'signMaskPolyfill', { - get: function() { - var mx = (this.x < 0.0 || 1/this.x === -Infinity) ? 1 : 0; - var my = (this.y < 0.0 || 1/this.y === -Infinity) ? 1 : 0; - return mx | my << 1; - } + Object.defineProperty(Float32x4Array.prototype, 'byteLength', { + get: function() { return this.length_ * Float32x4Array.BYTES_PER_ELEMENT; } }); -} -if (typeof SIMD.int32x4.flagX === "undefined") { - Object.defineProperty(SIMD.int32x4.prototype, 'flagX', { - get: function() { return this.x != 0x0; } + Object.defineProperty(Float32x4Array, 'BYTES_PER_ELEMENT', { + get: function() { return 16; } }); - Object.defineProperty(SIMD.int32x4.prototype, 'flagY', { - get: function() { return this.y != 0x0; } + Object.defineProperty(Float32x4Array.prototype, 'BYTES_PER_ELEMENT', { + get: function() { return 16; } }); - Object.defineProperty(SIMD.int32x4.prototype, 'flagZ', { - get: function() { return this.z != 0x0; } + Object.defineProperty(Float32x4Array.prototype, 'byteOffset', { + get: function() { return this.byteOffset_; } }); - Object.defineProperty(SIMD.int32x4.prototype, 'flagW', { - get: function() { return this.w != 0x0; } + Object.defineProperty(Float32x4Array.prototype, 'buffer', { + get: function() { return this.storage_.buffer; } }); -} -if (typeof SIMD.int32x4.signMaskPolyfill === "undefined") { - /** - * Extract the sign bit from each lane return them in the first 4 bits. - */ - Object.defineProperty(SIMD.int32x4.prototype, 'signMaskPolyfill', { - get: function() { - var mx = (this.x & 0x80000000) >>> 31; - var my = (this.y & 0x80000000) >>> 31; - var mz = (this.z & 0x80000000) >>> 31; - var mw = (this.w & 0x80000000) >>> 31; - return mx | my << 1 | mz << 2 | mw << 3; + Float32x4Array.prototype.getAt = function(i) { + if (i < 0) { + throw "Index must be >= 0."; } - }); -} + if (i >= this.length) { + throw "Index out of bounds."; + } + var x = this.storage_[i*4+0]; + var y = this.storage_[i*4+1]; + var z = this.storage_[i*4+2]; + var w = this.storage_[i*4+3]; + return SIMD.float32x4(x, y, z, w); + } -if (typeof SIMD.int16x8.signMaskPolyfill === "undefined") { - /** - * Extract the sign bit from each lane return them in the first 8 bits. - */ - Object.defineProperty(SIMD.int16x8.prototype, 'signMaskPolyfill', { - get: function() { - var ms0 = (this.s0 & 0x8000) >>> 15; - var ms1 = (this.s1 & 0x8000) >>> 15; - var ms2 = (this.s2 & 0x8000) >>> 15; - var ms3 = (this.s3 & 0x8000) >>> 15; - var ms4 = (this.s4 & 0x8000) >>> 15; - var ms5 = (this.s5 & 0x8000) >>> 15; - var ms6 = (this.s6 & 0x8000) >>> 15; - var ms7 = (this.s7 & 0x8000) >>> 15; - return ms0 | ms1 << 1 | ms2 << 2 | ms3 << 3 | - ms4 << 4 | ms5 << 5 | ms6 << 6 | ms7 << 7; + Float32x4Array.prototype.setAt = function(i, v) { + if (i < 0) { + throw "Index must be >= 0."; + } + if (i >= this.length) { + throw "Index out of bounds."; + } + if (!(v instanceof SIMD.float32x4)) { + throw "Value is not a float32x4."; + } + this.storage_[i*4+0] = v.x; + this.storage_[i*4+1] = v.y; + this.storage_[i*4+2] = v.z; + this.storage_[i*4+3] = v.w; + } +} + +if (typeof Int32x4Array === "undefined") { + Int32x4Array = function(a, b, c) { + if (_SIMD_PRIVATE.isNumber(a)) { + this.storage_ = new Int32Array(a*4); + this.length_ = a; + this.byteOffset_ = 0; + return; + } else if (_SIMD_PRIVATE.isTypedArray(a)) { + if (!(a instanceof Int32x4Array)) { + throw "Copying typed array of non-Int32x4Array is unimplemented."; + } + this.storage_ = new Int32Array(a.length * 4); + this.length_ = a.length; + this.byteOffset_ = 0; + // Copy ints. + for (var i = 0; i < a.length*4; i++) { + this.storage_[i] = a.storage_[i]; + } + } else if (_SIMD_PRIVATE.isArrayBuffer(a)) { + if ((b != undefined) && (b % Int32x4Array.BYTES_PER_ELEMENT) != 0) { + throw "byteOffset must be a multiple of 16."; + } + if (c != undefined) { + c *= 4; + this.storage_ = new Int32Array(a, b, c); + } + else { + // Note: new Int32Array(a, b) is NOT equivalent to new Int32Array(a, b, undefined) + this.storage_ = new Int32Array(a, b); + } + this.length_ = this.storage_.length / 4; + this.byteOffset_ = b != undefined ? b : 0; + } else { + throw "Unknown type of first argument."; } + } + + Object.defineProperty(Int32x4Array.prototype, 'length', { + get: function() { return this.length_; } }); -} -if (typeof SIMD.int8x16.signMaskPolyfill === "undefined") { - /** - * Extract the sign bit from each lane return them in the first 16 bits. - */ - Object.defineProperty(SIMD.int8x16.prototype, 'signMaskPolyfill', { - get: function() { - var ms0 = (this.s0 & 0x80) >>> 7; - var ms1 = (this.s1 & 0x80) >>> 7; - var ms2 = (this.s2 & 0x80) >>> 7; - var ms3 = (this.s3 & 0x80) >>> 7; - var ms4 = (this.s4 & 0x80) >>> 7; - var ms5 = (this.s5 & 0x80) >>> 7; - var ms6 = (this.s6 & 0x80) >>> 7; - var ms7 = (this.s7 & 0x80) >>> 7; - var ms8 = (this.s8 & 0x80) >>> 7; - var ms9 = (this.s9 & 0x80) >>> 7; - var ms10 = (this.s10 & 0x80) >>> 7; - var ms11 = (this.s11 & 0x80) >>> 7; - var ms12 = (this.s12 & 0x80) >>> 7; - var ms13 = (this.s13 & 0x80) >>> 7; - var ms14 = (this.s14 & 0x80) >>> 7; - var ms15 = (this.s15 & 0x80) >>> 7; - return ms0 | ms1 << 1 | ms2 << 2 | ms3 << 3 | - ms4 << 4 | ms5 << 5 | ms6 << 6 | ms7 << 7; - ms8 << 8 | ms9 << 9 | ms10 << 10 | ms11 << 11; - ms12 << 12 | ms13 << 13 | ms14 << 14 | ms15 << 15; - } + Object.defineProperty(Int32x4Array.prototype, 'byteLength', { + get: function() { return this.length_ * Int32x4Array.BYTES_PER_ELEMENT; } + }); + + Object.defineProperty(Int32x4Array, 'BYTES_PER_ELEMENT', { + get: function() { return 16; } + }); + + Object.defineProperty(Int32x4Array.prototype, 'BYTES_PER_ELEMENT', { + get: function() { return 16; } + }); + + Object.defineProperty(Int32x4Array.prototype, 'byteOffset', { + get: function() { return this.byteOffset_; } }); + + Object.defineProperty(Int32x4Array.prototype, 'buffer', { + get: function() { return this.storage_.buffer; } + }); + + Int32x4Array.prototype.getAt = function(i) { + if (i < 0) { + throw "Index must be >= 0."; + } + if (i >= this.length) { + throw "Index out of bounds."; + } + var x = this.storage_[i*4+0]; + var y = this.storage_[i*4+1]; + var z = this.storage_[i*4+2]; + var w = this.storage_[i*4+3]; + return SIMD.int32x4(x, y, z, w); + } + + Int32x4Array.prototype.setAt = function(i, v) { + if (i < 0) { + throw "Index must be >= 0."; + } + if (i >= this.length) { + throw "Index out of bounds."; + } + if (!(v instanceof SIMD.int32x4)) { + throw "Value is not a int32x4."; + } + this.storage_[i*4+0] = v.x; + this.storage_[i*4+1] = v.y; + this.storage_[i*4+2] = v.z; + this.storage_[i*4+3] = v.w; + } + + _SIMD_PRIVATE.isDataView = function(v) { + return v instanceof DataView; + } + + DataView.prototype.getFloat32x4 = function(byteOffset, littleEndian) { + if (!_SIMD_PRIVATE.isDataView(this)) + throw new TypeError("This is not a DataView."); + if (byteOffset < 0 || (byteOffset + 16) > this.buffer.byteLength) + throw new RangeError("The value of byteOffset is invalid."); + if (typeof littleEndian === 'undefined') + littleEndian = false; + return SIMD.float32x4(this.getFloat32(byteOffset, littleEndian), + this.getFloat32(byteOffset + 4, littleEndian), + this.getFloat32(byteOffset + 8, littleEndian), + this.getFloat32(byteOffset + 12, littleEndian)); + } + + DataView.prototype.getFloat64x2 = function(byteOffset, littleEndian) { + if (!_SIMD_PRIVATE.isDataView(this)) + throw new TypeError("This is not a DataView."); + if (byteOffset < 0 || (byteOffset + 16) > this.buffer.byteLength) + throw new RangeError("The value of byteOffset is invalid."); + if (typeof littleEndian === 'undefined') + littleEndian = false; + return SIMD.float64x2(this.getFloat64(byteOffset, littleEndian), + this.getFloat64(byteOffset + 8, littleEndian)); + } + + DataView.prototype.getInt32x4 = function(byteOffset, littleEndian) { + if (!_SIMD_PRIVATE.isDataView(this)) + throw new TypeError("This is not a DataView."); + if (byteOffset < 0 || (byteOffset + 16) > this.buffer.byteLength) + throw new RangeError("The value of byteOffset is invalid."); + if (typeof littleEndian === 'undefined') + littleEndian = false; + return SIMD.int32x4(this.getInt32(byteOffset, littleEndian), + this.getInt32(byteOffset + 4, littleEndian), + this.getInt32(byteOffset + 8, littleEndian), + this.getInt32(byteOffset + 12, littleEndian)); + } + + DataView.prototype.getInt16x8 = function(byteOffset, littleEndian) { + if (!_SIMD_PRIVATE.isDataView(this)) + throw new TypeError("This is not a DataView."); + if (byteOffset < 0 || (byteOffset + 16) > this.buffer.byteLength) + throw new RangeError("The value of byteOffset is invalid."); + if (typeof littleEndian === 'undefined') + littleEndian = false; + return SIMD.int16x8(this.getInt16(byteOffset, littleEndian), + this.getInt16(byteOffset + 2, littleEndian), + this.getInt16(byteOffset + 4, littleEndian), + this.getInt16(byteOffset + 6, littleEndian), + this.getInt16(byteOffset + 8, littleEndian), + this.getInt16(byteOffset + 10, littleEndian), + this.getInt16(byteOffset + 12, littleEndian), + this.getInt16(byteOffset + 14, littleEndian)); + } + + DataView.prototype.getInt8x16 = function(byteOffset, littleEndian) { + if (!_SIMD_PRIVATE.isDataView(this)) + throw new TypeError("This is not a DataView."); + if (byteOffset < 0 || (byteOffset + 16) > this.buffer.byteLength) + throw new RangeError("The value of byteOffset is invalid."); + if (typeof littleEndian === 'undefined') + littleEndian = false; + return SIMD.int8x16(this.getInt8(byteOffset, littleEndian), + this.getInt8(byteOffset + 1, littleEndian), + this.getInt8(byteOffset + 2, littleEndian), + this.getInt8(byteOffset + 3, littleEndian), + this.getInt8(byteOffset + 4, littleEndian), + this.getInt8(byteOffset + 5, littleEndian), + this.getInt8(byteOffset + 6, littleEndian), + this.getInt8(byteOffset + 7, littleEndian), + this.getInt8(byteOffset + 8, littleEndian), + this.getInt8(byteOffset + 9, littleEndian), + this.getInt8(byteOffset + 10, littleEndian), + this.getInt8(byteOffset + 11, littleEndian), + this.getInt8(byteOffset + 12, littleEndian), + this.getInt8(byteOffset + 13, littleEndian), + this.getInt8(byteOffset + 14, littleEndian), + this.getInt8(byteOffset + 15, littleEndian)); + } + + DataView.prototype.setFloat32x4 = function(byteOffset, value, littleEndian) { + if (!_SIMD_PRIVATE.isDataView(this)) + throw new TypeError("This is not a DataView."); + if (byteOffset < 0 || (byteOffset + 16) > this.buffer.byteLength) + throw new RangeError("The value of byteOffset is invalid."); + value = SIMD.float32x4(value); + if (typeof littleEndian === 'undefined') + littleEndian = false; + this.setFloat32(byteOffset, value.x, littleEndian); + this.setFloat32(byteOffset + 4, value.y, littleEndian); + this.setFloat32(byteOffset + 8, value.z, littleEndian); + this.setFloat32(byteOffset + 12, value.w, littleEndian); + } + + DataView.prototype.setFloat64x2 = function(byteOffset, value, littleEndian) { + if (!_SIMD_PRIVATE.isDataView(this)) + throw new TypeError("This is not a DataView."); + if (byteOffset < 0 || (byteOffset + 16) > this.buffer.byteLength) + throw new RangeError("The value of byteOffset is invalid."); + value = SIMD.float64x2(value); + if (typeof littleEndian === 'undefined') + littleEndian = false; + this.setFloat64(byteOffset, value.x, littleEndian); + this.setFloat64(byteOffset + 8, value.y, littleEndian); + } + + DataView.prototype.setInt32x4 = function(byteOffset, value, littleEndian) { + if (!_SIMD_PRIVATE.isDataView(this)) + throw new TypeError("This is not a DataView."); + if (byteOffset < 0 || (byteOffset + 16) > this.buffer.byteLength) + throw new RangeError("The value of byteOffset is invalid."); + value = SIMD.int32x4(value); + if (typeof littleEndian === 'undefined') + littleEndian = false; + this.setInt32(byteOffset, value.x, littleEndian); + this.setInt32(byteOffset + 4, value.y, littleEndian); + this.setInt32(byteOffset + 8, value.z, littleEndian); + this.setInt32(byteOffset + 12, value.w, littleEndian); + } + + DataView.prototype.setInt16x8 = function(byteOffset, value, littleEndian) { + if (!_SIMD_PRIVATE.isDataView(this)) + throw new TypeError("This is not a DataView."); + if (byteOffset < 0 || (byteOffset + 16) > this.buffer.byteLength) + throw new RangeError("The value of byteOffset is invalid."); + value = SIMD.int16x8(value); + if (typeof littleEndian === 'undefined') + littleEndian = false; + this.setInt16(byteOffset, value.s0, littleEndian); + this.setInt16(byteOffset + 2, value.s1, littleEndian); + this.setInt16(byteOffset + 4, value.s2, littleEndian); + this.setInt16(byteOffset + 6, value.s3, littleEndian); + this.setInt16(byteOffset + 8, value.s4, littleEndian); + this.setInt16(byteOffset + 10, value.s5, littleEndian); + this.setInt16(byteOffset + 12, value.s6, littleEndian); + this.setInt16(byteOffset + 14, value.s7, littleEndian); + } + + DataView.prototype.setInt8x16 = function(byteOffset, value, littleEndian) { + if (!_SIMD_PRIVATE.isDataView(this)) + throw new TypeError("This is not a DataView."); + if (byteOffset < 0 || (byteOffset + 16) > this.buffer.byteLength) + throw new RangeError("The value of byteOffset is invalid."); + value = SIMD.int8x16(value); + if (typeof littleEndian === 'undefined') + littleEndian = false; + this.setInt8(byteOffset, value.s0, littleEndian); + this.setInt8(byteOffset + 1, value.s1, littleEndian); + this.setInt8(byteOffset + 2, value.s2, littleEndian); + this.setInt8(byteOffset + 3, value.s3, littleEndian); + this.setInt8(byteOffset + 4, value.s4, littleEndian); + this.setInt8(byteOffset + 5, value.s5, littleEndian); + this.setInt8(byteOffset + 6, value.s6, littleEndian); + this.setInt8(byteOffset + 7, value.s7, littleEndian); + this.setInt8(byteOffset + 8, value.s8, littleEndian); + this.setInt8(byteOffset + 9, value.s9, littleEndian); + this.setInt8(byteOffset + 10, value.s10, littleEndian); + this.setInt8(byteOffset + 11, value.s11, littleEndian); + this.setInt8(byteOffset + 12, value.s12, littleEndian); + this.setInt8(byteOffset + 13, value.s13, littleEndian); + this.setInt8(byteOffset + 14, value.s14, littleEndian); + this.setInt8(byteOffset + 15, value.s15, littleEndian); + } } diff --git a/src/library_async.js b/src/library_async.js index 0e527f7aad203..10411543e9af9 100644 --- a/src/library_async.js +++ b/src/library_async.js @@ -185,9 +185,56 @@ mergeInto(LibraryManager.library, { ___async = 1; } #else // ASYNCIFY + +#if EMTERPRETIFY_ASYNC + + // Emterpreter sync=>async support + // + // The idea here is that almost all interpreter frames are already on the stack (the + // emterpreter stack), so it's easy to save a callstack and reload it, we just need + // to also save the pc. + // Saving state keeps the pc right before the current call. That means when we reload, + // we are going to re-call in the exact same way as before - including the final call + // to the async function here! Therefore sleep etc. detect the state, so they know + // if they are the first call or the second. The second typically does nothing, but + // if there is a return value it could return it, etc. (TODO: support return values) + $EmterpreterAsync: { + state: 0, // 0 - nothing + // 1 - saving + // 2 - loading + setState: function(s) { + this.state = s; + asm.setAsyncState(s); + }, + }, + + emscripten_sleep__deps: ['$EmterpreterAsync'], + emscripten_sleep: function(ms) { + if (EmterpreterAsync.state === 0) { + // save the stack we want to resume. this lets other code run in between + // XXX this assumes that this stack top never ever leak! exceptions might violate that + var stack = new Int32Array(HEAP32.subarray(EMTSTACKTOP>>2, asm.emtStackSave()>>2)); + Browser.safeSetTimeout(function resume() { + assert(EmterpreterAsync.state === 1); + // copy the stack back in and resume + HEAP32.set(stack, EMTSTACKTOP>>2); + EmterpreterAsync.setState(2); + asm.emterpret(stack[0]); // pc of the first function, from which we can reconstruct the rest, is at position 0 on the stack + }, ms); + EmterpreterAsync.setState(1); + } else { + // nothing to do here, the stack was just recreated. reset the state. + assert(EmterpreterAsync.state === 2); + EmterpreterAsync.setState(0); + } + }, + +#else emscripten_sleep: function() { throw 'Please compile your program with -s ASYNCIFY=1 in order to use asynchronous operations like emscripten_sleep'; }, +#endif + emscripten_coroutine_create: function() { throw 'Please compile your program with -s ASYNCIFY=1 in order to use asynchronous operations like emscripten_coroutine_create'; }, diff --git a/src/library_sdl.js b/src/library_sdl.js index 839f7f1b2f6a4..f9cfe258f2daa 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -1648,12 +1648,19 @@ var LibrarySDL = { // We actually do the whole screen in Unlock... }, +#if EMTERPRETIFY_ASYNC == 0 SDL_Delay: function(delay) { if (!ENVIRONMENT_IS_WORKER) abort('SDL_Delay called on the main thread! Potential infinite loop, quitting.'); // horrible busy-wait, but in a worker it at least does not block rendering var now = Date.now(); while (Date.now() - now < delay) {} }, +#else + SDL_Delay__deps: ['emscripten_sleep'], + SDL_Delay: function(delay) { + _emscripten_sleep(delay); + }, +#endif SDL_WM_SetCaption: function(title, icon) { title = title && Pointer_stringify(title); @@ -2291,11 +2298,10 @@ var LibrarySDL = { SDL.audio.queueNewAudioData = function SDL_queueNewAudioData() { if (!SDL.audio) return; - var secsUntilNextPlayStart = SDL.audio.nextPlayTime - SDL.audioContext['currentTime']; - for(var i = 0; i < SDL.audio.numSimultaneouslyQueuedBuffers; ++i) { // Only queue new data if we don't have enough audio data already in queue. Otherwise skip this time slot // and wait to queue more in the next time the callback is run. + var secsUntilNextPlayStart = SDL.audio.nextPlayTime - SDL.audioContext['currentTime']; if (secsUntilNextPlayStart >= SDL.audio.bufferingDelay + SDL.audio.bufferDurationSecs*SDL.audio.numSimultaneouslyQueuedBuffers) return; // Ask SDL audio data from the user code. diff --git a/src/settings.js b/src/settings.js index 9795a76a47f33..b1c59c0bbeabb 100644 --- a/src/settings.js +++ b/src/settings.js @@ -576,6 +576,7 @@ var NO_DYNAMIC_EXECUTION = 0; // When enabled, we do not emit eval() and new Fun var EMTERPRETIFY = 0; // Runs tools/emterpretify on the compiler output var EMTERPRETIFY_BLACKLIST = []; // Functions to not emterpret, that is, to run normally at full speed +var EMTERPRETIFY_ASYNC = 0; // Allows sync code in the emterpreter, by saving the call stack, doing an async delay, and resuming it var RUNNING_JS_OPTS = 0; // whether js opts will be run, after the main compiler var RUNNING_FASTCOMP = 1; // whether we are running the fastcomp backend diff --git a/system/include/emscripten/vector.h b/system/include/emscripten/vector.h index 541ccb6a7e661..46305bad5b3a9 100644 --- a/system/include/emscripten/vector.h +++ b/system/include/emscripten/vector.h @@ -42,6 +42,11 @@ int32x4 emscripten_int32x4_select(int32x4 __a, int32x4 __b, int32x4 __c) __attri float32x4 emscripten_float32x4_fromInt32x4Bits(int32x4 __a) __attribute__((__nothrow__, __const__)); float32x4 emscripten_float32x4_fromInt32x4(int32x4 __a) __attribute__((__nothrow__, __const__)); +float32x4 emscripten_float32x4_loadx(const void *__p) __attribute__((__nothrow__, __const__)); +float32x4 emscripten_float32x4_loadxy(const void *__p) __attribute__((__nothrow__, __const__)); +void emscripten_float32x4_storex(const void *__p, float32x4 __a) __attribute__((__nothrow__)); +void emscripten_float32x4_storexy(const void *__p, float32x4 __a) __attribute__((__nothrow__)); + #ifdef __cplusplus } #endif diff --git a/system/include/emscripten/xmmintrin.h b/system/include/emscripten/xmmintrin.h index 8e74688ff5cc1..7ffce688ca4a5 100644 --- a/system/include/emscripten/xmmintrin.h +++ b/system/include/emscripten/xmmintrin.h @@ -53,17 +53,21 @@ _mm_load_ps(const float *__p) static __inline__ __m128 __attribute__((__always_inline__)) _mm_loadl_pi(__m128 __a, const void /*__m64*/ *__p) { - // TODO: This actually corresponds to the SIMD.float32x4.loadXY function in - // SIMD.js. Use that instead. +#if 0 // TODO: Re-enable these when we have full support + return __builtin_shufflevector(emscripten_float32x4_loadxy(__p), __a, 0, 1, 4, 5); +#else return (__m128){ ((const float*)__p)[0], ((const float*)__p)[1], __a[2], __a[3] }; +#endif } static __inline__ __m128 __attribute__((__always_inline__)) _mm_loadh_pi(__m128 __a, const void /*__m64*/ *__p) { - // TODO: Due to alignment masking, this would probably be faster as a loadXY - // followed by a shuffle. +#if 0 // TODO: Re-enable these when we have full support + return __builtin_shufflevector(__a, emscripten_float32x4_loadxy(__p), 0, 1, 4, 5); +#else return (__m128){ __a[0], __a[1], ((const float*)__p)[0], ((const float*)__p)[1] }; +#endif } static __inline__ __m128 __attribute__((__always_inline__)) @@ -94,27 +98,33 @@ _mm_load_ps1(const float *__p) static __inline__ __m128 __attribute__((__always_inline__)) _mm_load_ss(const float *__p) { - // TODO: This actually corresponds to the SIMD.float32x4.loadX function in - // SIMD.js. Use that instead. +#if 0 // TODO: Re-enable these when we have full support + return emscripten_float32x4_loadx(__p); +#else return (__m128){ *__p, 0.0f, 0.0f, 0.0f }; +#endif } static __inline__ void __attribute__((__always_inline__)) _mm_storel_pi(void /*__m64*/ *__p, __m128 __a) { - // TODO: This actually corresponds to the SIMD.float32x4.storeXY function in - // SIMD.js. Use that instead. +#if 0 // TODO: Re-enable these when we have full support + emscripten_float32x4_storexy(__p, __a); +#else ((float*)__p)[0] = __a[0]; ((float*)__p)[1] = __a[1]; +#endif } static __inline__ void __attribute__((__always_inline__)) _mm_storeh_pi(void /*__m64*/ *__p, __m128 __a) { - // TODO: Due to alignment masking, on x64 this would be faster as a sizzle - // and a storeXY, so we should use that instead. +#if 0 // TODO: Re-enable these when we have full support + emscripten_float32x4_storexy(__p, __builtin_shufflevector(__a, __a, 2, 3, 0, 1)); +#else ((float*)__p)[0] = __a[2]; ((float*)__p)[1] = __a[3]; +#endif } static __inline__ void __attribute__((__always_inline__)) @@ -152,7 +162,11 @@ _mm_store_ps1(float *__p, __m128 __a) static __inline__ void __attribute__((__always_inline__)) _mm_store_ss(float *__p, __m128 __a) { +#if 0 // TODO: Re-enable these when we have full support + emscripten_float32x4_storex(__p, __a); +#else *__p = __a[0]; +#endif } static __inline__ void __attribute__((__always_inline__)) diff --git a/system/include/libcxx/type_traits b/system/include/libcxx/type_traits index bd10697cae795..4beaf74970343 100644 --- a/system/include/libcxx/type_traits +++ b/system/include/libcxx/type_traits @@ -420,9 +420,12 @@ template struct _LIBCPP_TYPE_VIS_ONLY is_same<_Tp, _Tp> : namespace __libcpp_is_function_imp { +struct __dummy_type {}; template char __test(_Tp*); +template char __test(__dummy_type); template __two __test(...); -template _Tp& __source(); +template _Tp& __source(int); +template __dummy_type __source(long); } template ::value || @@ -431,7 +434,7 @@ template ::value || is_reference<_Tp>::value || __is_nullptr_t<_Tp>::value > struct __libcpp_is_function - : public integral_constant(__libcpp_is_function_imp::__source<_Tp>())) == 1> + : public integral_constant(__libcpp_is_function_imp::__source<_Tp>(0))) == 1> {}; template struct __libcpp_is_function<_Tp, true> : public false_type {}; diff --git a/tests/embind/imvu_test_adapter.js b/tests/embind/imvu_test_adapter.js index 93eeab37dd194..50777ba651fa5 100644 --- a/tests/embind/imvu_test_adapter.js +++ b/tests/embind/imvu_test_adapter.js @@ -1,6 +1,6 @@ /* The embind test suite (embind.test.js) is configured to be runnable in two different testing engines: - The Emscripten python test runner (open-source in emscripten repository) and - - The IMVU test runner (closed-source in IMVU repository) + - The IMVU test runner (open-source via imvujs, available at https://github.com/imvu/imvujs) Embind (and its tests) were originally developed in IMVU repository, which is the reason for two testing architectures. This adapter file is used when the embind tests are run as part of the Emscripten test runner, to provide the necessary glue code to adapt the tests to Emscripten runner. @@ -83,6 +83,7 @@ function module(ignore, func) { } return false; } catch (e) { + console.error(e.stack); console.error('error:', e); return {stack: e.stack, e: e}; } @@ -211,7 +212,7 @@ function module(ignore, func) { */ }; -// var assert = { + var assert = {}; //////////////////////////////////////////////////////////////////////////////// // GENERAL STATUS @@ -550,6 +551,7 @@ function module(ignore, func) { } } + (function() { var g = 'undefined' === typeof window ? global : window; // synonyms @@ -593,7 +595,7 @@ function module(ignore, func) { g.requestAnimationFrame = function() { throw new AssertionError("Don't call requestAnimationFrame in tests. Use fakes."); }; -//})(); + })(); // Emscripten runner starts all tests from this function. // IMVU runner uses a separate runner & reporting mechanism. diff --git a/tests/embind/test.post.js b/tests/embind/test.post.js new file mode 100644 index 0000000000000..e5a8207c22d7b --- /dev/null +++ b/tests/embind/test.post.js @@ -0,0 +1,2 @@ + return Module; +})(); diff --git a/tests/embind/test.pre.js b/tests/embind/test.pre.js new file mode 100644 index 0000000000000..f0fb17b5cd000 --- /dev/null +++ b/tests/embind/test.pre.js @@ -0,0 +1 @@ +(function(){return this;})()['Module'] = (function() { diff --git a/tests/emterpreter_async.cpp b/tests/emterpreter_async.cpp new file mode 100644 index 0000000000000..198a0ec1731a0 --- /dev/null +++ b/tests/emterpreter_async.cpp @@ -0,0 +1,18 @@ +#include +#include +#include + +int main() { + // infinite main loop, turned async using emterpreter + int counter = 0; + while (1) { + printf("frame: %d\n", ++counter); + emscripten_sleep(100); + if (counter == 10) { + int result = 1; + REPORT_RESULT(); + break; + } + } +} + diff --git a/tests/emterpreter_async_2.cpp b/tests/emterpreter_async_2.cpp new file mode 100644 index 0000000000000..4f4342320d138 --- /dev/null +++ b/tests/emterpreter_async_2.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +int calc(int x) { + printf("..%d..\n", x); + if (x < 5) { + char buffer[10000]; + emscripten_get_callstack(EM_LOG_JS_STACK, buffer, 10000); + int newlines = 0; + char *b = buffer; + while (*b) { + if (*b == '\n') newlines++; + b++; + } + printf("stack: %s => %d, sleeping...\n", buffer, newlines); + emscripten_sleep(1000); + printf("..and we're back, returning %d!\n", newlines); + return newlines; + } + if (x % 6 == 0) return calc(5*x/6); + if (x % 4 == 1) return calc(x-2); + return calc(x-1); +} + +int main() { + volatile int x = 100; + volatile int result = calc(x); + printf("calc(%d) = %d\n", x, result); + REPORT_RESULT(); +} + diff --git a/tests/optimizer/asmLastOpts-output.js b/tests/optimizer/asmLastOpts-output.js new file mode 100644 index 0000000000000..4bf7595e3df09 --- /dev/null +++ b/tests/optimizer/asmLastOpts-output.js @@ -0,0 +1,10 @@ +function test() { + if (HEAP32[i5 >> 2] | 0) { + if ((_fread(i4 | 0, 1, 257, HEAP32[i5 >> 2] | 0) | 0) != 257) i31 = 9; else if ((HEAPU8[i4 >> 0] | 0 | 0) != (HEAP32[84328] | 0)) i31 = 9; else if (_memcmp(i4 + 1 | 0, HEAP32[i20 >> 2] | 0, 256) | 0) i31 = 9; else if ((_fread(HEAP32[i16 >> 2] | 0, 256, 256, HEAP32[i5 >> 2] | 0) | 0) != 256) i31 = 9; + } else i31 = 9; + barrier(); + if (HEAP32[i5 >> 2] | 0) { + if ((_fread(i4 | 0, 1, 257, HEAP32[i5 >> 2] | 0) | 0) != 257) if ((HEAPU8[i4 >> 0] | 0 | 0) != (HEAP32[84328] | 0)) if (_memcmp(i4 + 1 | 0, HEAP32[i20 >> 2] | 0, 256) | 0) if ((_fread(HEAP32[i16 >> 2] | 0, 256, 256, HEAP32[i5 >> 2] | 0) | 0) != 256) i31 = 9; + } else i31 = 9; +} + diff --git a/tests/optimizer/asmLastOpts.js b/tests/optimizer/asmLastOpts.js new file mode 100644 index 0000000000000..7b05a264a6535 --- /dev/null +++ b/tests/optimizer/asmLastOpts.js @@ -0,0 +1,37 @@ +function test() { + if ((HEAP32[i5 >> 2] | 0) != 0) { + if ((_fread(i4 | 0, 1, 257, HEAP32[i5 >> 2] | 0) | 0) != 257) { + i31 = 9; + } else { + if ((HEAPU8[i4 >> 0] | 0 | 0) != (HEAP32[84328] | 0)) { + i31 = 9; + } else { + if ((_memcmp(i4 + 1 | 0, HEAP32[i20 >> 2] | 0, 256) | 0) != 0) { + i31 = 9; + } else { + if ((_fread(HEAP32[i16 >> 2] | 0, 256, 256, HEAP32[i5 >> 2] | 0) | 0) != 256) { + i31 = 9; + } + } + } + } + } else { + i31 = 9; + } + barrier(); + if ((HEAP32[i5 >> 2] | 0) != 0) { + if ((_fread(i4 | 0, 1, 257, HEAP32[i5 >> 2] | 0) | 0) != 257) { + if ((HEAPU8[i4 >> 0] | 0 | 0) != (HEAP32[84328] | 0)) { + if ((_memcmp(i4 + 1 | 0, HEAP32[i20 >> 2] | 0, 256) | 0) != 0) { + if ((_fread(HEAP32[i16 >> 2] | 0, 256, 256, HEAP32[i5 >> 2] | 0) | 0) != 256) { + i31 = 9; + } + } + } + } + } else { + i31 = 9; + } +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["test"] + diff --git a/tests/sdl2_unwasteful.cpp b/tests/sdl2_unwasteful.cpp new file mode 100644 index 0000000000000..65034c25bec0f --- /dev/null +++ b/tests/sdl2_unwasteful.cpp @@ -0,0 +1,65 @@ +#include +#include + +#define TOTAL_RUNS 20 + +static SDL_Window *window; +static SDL_Surface *surface; + +static void sdlError(const char *str) +{ + fprintf(stderr, "Error at %s: %s\n", str, SDL_GetError()); + emscripten_force_exit(1); +} + +static void main_loop(void) +{ + static unsigned int runs = 0; + + // verify that the ctx and image do not change from frame to frame + if (runs == 1) { + EM_ASM({ + Module.the_ctx = Module.SDL2.ctx; + Module.the_image = Module.SDL2.image; + Module.print('start with ' + [Module.the_ctx, Module.the_image]); + assert(!!Module.the_ctx && (typeof Module.the_ctx === 'object'), 'typeof ctx'); + assert(!!Module.the_image && (typeof Module.the_image === 'object'), 'typeof image'); + Module.print('set values'); + }); + } else if (runs > 1) { + EM_ASM_ARGS({ + assert(Module.the_ctx === Module.SDL2.ctx, 'ctx'); + assert(Module.the_image === Module.SDL2.image, 'image'); + Module.print('check ok ' + $0); + }, runs); + } + + int i; + if (SDL_LockSurface(surface) != 0) sdlError("SDL_LockSurface"); + SDL_UnlockSurface(surface); // does not return a value + if (SDL_UpdateWindowSurface(window) != 0) + sdlError("SDL_UpdateWindowSurface"); + + runs++; + if (runs >= TOTAL_RUNS) { + emscripten_cancel_main_loop(); + int result = 1; + REPORT_RESULT(); + } +} + +int main(void) +{ + if (SDL_Init(SDL_INIT_VIDEO) != 0) sdlError("SDL_Init"); + + window = SDL_CreateWindow("SDL 2 test", + 0, 0, + 640, 480, + SDL_WINDOW_SHOWN); + if (window == NULL) sdlError("SDL_CreateWindow"); + surface = SDL_GetWindowSurface(window); + if (surface == NULL) sdlError("SDL_GetWindowSurface"); + + emscripten_set_main_loop(main_loop, 0, 1); +} + diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py index ad0a6d29b061c..dfbd3b2a2c697 100644 --- a/tests/test_benchmark.py +++ b/tests/test_benchmark.py @@ -12,7 +12,7 @@ # 5: 10 seconds DEFAULT_ARG = '4' -TEST_REPS = 2 +TEST_REPS = 3 CORE_BENCHMARKS = True # core benchmarks vs full regression suite @@ -134,7 +134,7 @@ def run(self, args): benchmarkers_error = '' benchmarkers = [ #NativeBenchmarker('clang', CLANG_CC, CLANG), - NativeBenchmarker(default_native_name, os.path.join(default_native, 'clang'), os.path.join(default_native, 'clang++')), + #NativeBenchmarker(default_native_name, os.path.join(default_native, 'clang'), os.path.join(default_native, 'clang++')), #NativeBenchmarker('clang-3.2-O3', os.path.join(default_native, 'clang'), os.path.join(default_native, 'clang++'), ['-O3']), #NativeBenchmarker('clang-3.3', os.path.join(LLVM_3_3, 'clang'), os.path.join(LLVM_3_3, 'clang++')), #NativeBenchmarker('clang-3.4', os.path.join(LLVM_3_4, 'clang'), os.path.join(LLVM_3_4, 'clang++')), diff --git a/tests/test_browser.py b/tests/test_browser.py index 3d955ce7378c6..cba683c430d85 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -123,6 +123,7 @@ def build_native_lzma(self): os.chdir(cwd) def test_split(self): + return self.skip('non-fastcomp is deprecated and fails in 3.5') def nfc(): # test HTML generation. self.reftest(path_from_root('tests', 'htmltest.png')) @@ -218,6 +219,7 @@ def nfc(): nonfastcomp(nfc) def test_split_in_source_filenames(self): + return self.skip('non-fastcomp is deprecated and fails in 3.5') def nfc(): self.reftest(path_from_root('tests', 'htmltest.png')) output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.js', '-g', '--split', '100', '--pre-js', 'reftest.js']).communicate() @@ -2442,3 +2444,12 @@ def test_sdl2_fog_linear(self): args=['-s', 'USE_SDL=2', '-s', 'USE_SDL_IMAGE=2','--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], message='You should see an image with fog.') + def test_sdl2_unwasteful(self): + self.btest('sdl2_unwasteful.cpp', expected='1', args=['-s', 'USE_SDL=2', '-O1']) + + def test_emterpreter_async(self): + self.btest('emterpreter_async.cpp', '1', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-O3', '-g2']) + + def test_emterpreter_async_2(self): + self.btest('emterpreter_async_2.cpp', '47', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-O3']) + diff --git a/tests/test_core.py b/tests/test_core.py index 2000349742c28..519d8a770db4d 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -7136,10 +7136,9 @@ def test_64bit_return_value(self): assert "low = 5678" in out assert "high = 1234" in out - def test_asyncify(self): - if not Settings.ASM_JS: return self.skip('asyncify requires asm.js') - if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('asyncify requires fastcomp') - if self.is_emterpreter(): return self.skip('todo') + def test_async(self): + if not Settings.ASM_JS: return self.skip('async requires asm.js') + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('async requires fastcomp') self.banned_js_engines = [SPIDERMONKEY_ENGINE, V8_ENGINE] # needs setTimeout which only node has @@ -7159,7 +7158,12 @@ def test_asyncify(self): printf("%d\n", i); } ''' - Settings.ASYNCIFY = 1; + + if not self.is_emterpreter(): + Settings.ASYNCIFY = 1 + else: + Settings.EMTERPRETIFY_ASYNC = 1 + self.do_run(src, 'HelloWorld!99'); def test_coroutine(self): diff --git a/tests/test_other.py b/tests/test_other.py index d3723aa9a490d..7ba58f332488c 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -1918,6 +1918,8 @@ def test_js_optimizer(self): ['asm', 'asmPreciseF32', 'optimizeFrounds']), (path_from_root('tests', 'optimizer', 'test-js-optimizer-asm-last.js'), [open(path_from_root('tests', 'optimizer', 'test-js-optimizer-asm-lastOpts-output.js')).read(), open(path_from_root('tests', 'optimizer', 'test-js-optimizer-asm-lastOpts-output2.js')).read(), open(path_from_root('tests', 'optimizer', 'test-js-optimizer-asm-lastOpts-output3.js')).read()], ['asm', 'asmLastOpts']), + (path_from_root('tests', 'optimizer', 'asmLastOpts.js'), open(path_from_root('tests', 'optimizer', 'asmLastOpts-output.js')).read(), + ['asm', 'asmLastOpts']), (path_from_root('tests', 'optimizer', 'test-js-optimizer-asm-last.js'), [open(path_from_root('tests', 'optimizer', 'test-js-optimizer-asm-last-output.js')).read(), open(path_from_root('tests', 'optimizer', 'test-js-optimizer-asm-last-output2.js')).read(), open(path_from_root('tests', 'optimizer', 'test-js-optimizer-asm-last-output3.js')).read()], ['asm', 'asmLastOpts', 'last']), (path_from_root('tests', 'optimizer', 'test-js-optimizer-asm-relocate.js'), open(path_from_root('tests', 'optimizer', 'test-js-optimizer-asm-relocate-output.js')).read(), @@ -2084,9 +2086,29 @@ def test_embind(self): print args, fail self.clear() try_delete(self.in_dir('a.out.js')) - Popen([PYTHON, EMCC, path_from_root('tests', 'embind', 'embind_test.cpp'), '--post-js', path_from_root('tests', 'embind', 'underscore-1.4.2.js'), '--post-js', path_from_root('tests', 'embind', 'imvu_test_adapter.js'), '--post-js', path_from_root('tests', 'embind', 'embind.test.js')] + args, stderr=PIPE if fail else None, env=environ).communicate() + + testFiles = [ + path_from_root('tests', 'embind', 'underscore-1.4.2.js'), + path_from_root('tests', 'embind', 'imvu_test_adapter.js'), + path_from_root('tests', 'embind', 'embind.test.js'), + ] + + Popen( + [ PYTHON, + EMCC, + path_from_root('tests', 'embind', 'embind_test.cpp'), + '--pre-js', path_from_root('tests', 'embind', 'test.pre.js'), + '--post-js', path_from_root('tests', 'embind', 'test.post.js'), + ] + args, + stderr=PIPE if fail else None, + env=environ).communicate() + assert os.path.exists(self.in_dir('a.out.js')) == (not fail) if not fail: + with open(self.in_dir('a.out.js'), 'ab') as f: + for tf in testFiles: + f.write(open(tf, 'rb').read()) + output = run_js(self.in_dir('a.out.js'), stdout=PIPE, stderr=PIPE, full_output=True, assert_returncode=0) assert "FAIL" not in output, output @@ -4244,7 +4266,7 @@ def test_emterpreter(self): def do_emcc_test(source, args, output, emcc_args=[]): print print 'emcc', source[:40], '\n' in source - self.clear() + try_delete('a.out.js') if '\n' in source: open('src.cpp', 'w').write(source) source = 'src.cpp' @@ -4276,7 +4298,7 @@ def do_test(source, args, output): else: source = path_from_root('tests', source) Popen([PYTHON, EMCC, source, '-O2', '--profiling', '-s', 'FINALIZE_ASM_JS=0', '-s', 'GLOBAL_BASE=2048']).communicate() - Popen([PYTHON, path_from_root('tools', 'emterpretify.py'), 'a.out.js', 'em.out.js']).communicate() + Popen([PYTHON, path_from_root('tools', 'emterpretify.py'), 'a.out.js', 'em.out.js', 'ASYNC=0']).communicate() self.assertTextDataContained(output, run_js('a.out.js', args=args)) self.assertTextDataContained(output, run_js('em.out.js', args=args)) out = run_js('em.out.js', engine=SPIDERMONKEY_ENGINE, args=args, stderr=PIPE, full_output=True) @@ -4300,7 +4322,7 @@ def do_js_test(name, source, args, output): source = default.replace('{{{MAIN}}}', source) open('a.out.js', 'w').write(source) open('a.out.js.mem', 'wb').write(default_mem) - Popen([PYTHON, path_from_root('tools', 'emterpretify.py'), 'a.out.js', 'em.out.js']).communicate() + Popen([PYTHON, path_from_root('tools', 'emterpretify.py'), 'a.out.js', 'em.out.js', 'ASYNC=0']).communicate() sm_no_warn = filter(lambda x: x != '-w', SPIDERMONKEY_ENGINE) self.assertTextDataContained(output, run_js('a.out.js', engine=sm_no_warn, args=args)) # run in spidermonkey for print() self.assertTextDataContained(output, run_js('em.out.js', engine=sm_no_warn, args=args)) @@ -4311,8 +4333,40 @@ def do_js_test(name, source, args, output): do_test('hello_world_loop.cpp', [], 'hello, world!') do_test('fannkuch.cpp', ['5'], 'Pfannkuchen(5) = 7.') - # do not emterpret main, but still emterpret worker - do_emcc_test('fannkuch.cpp', ['5'], 'Pfannkuchen(5) = 7.', ['-s', 'EMTERPRETIFY_BLACKLIST=["_main"]']) + # blacklisting checks + + def get_func(src, name): + start = src.index('function ' + name + '(') + t = start + n = 0 + while True: + if src[t] == '{': n += 1 + elif src[t] == '}': + n -= 1 + if n == 0: return src[start:t+1] + t += 1 + assert t < len(src) + + do_emcc_test('fannkuch.cpp', ['5'], 'Pfannkuchen(5) = 7.', []) + src = open('a.out.js').read() + assert 'emterpret' in get_func(src, '_main'), 'main is emterpreted' + assert 'function _atoi(' not in src, 'atoi is emterpreted and does not even have a trampoline, since only other emterpreted can reach it' + + do_emcc_test('fannkuch.cpp', ['5'], 'Pfannkuchen(5) = 7.', ['-s', 'EMTERPRETIFY_BLACKLIST=["_main"]']) # blacklist main + src = open('a.out.js').read() + assert 'emterpret' not in get_func(src, '_main'), 'main is NOT emterpreted, it was blacklisted' + assert 'emterpret' in get_func(src, '_atoi'), 'atoi is emterpreted' + + do_emcc_test('fannkuch.cpp', ['5'], 'Pfannkuchen(5) = 7.', ['-s', 'EMTERPRETIFY_BLACKLIST=["_main", "_atoi"]']) # blacklist main and atoi + src = open('a.out.js').read() + assert 'emterpret' not in get_func(src, '_main'), 'main is NOT emterpreted, it was blacklisted' + assert 'emterpret' not in get_func(src, '_atoi'), 'atoi is NOT emterpreted either' + + open('blacklist.txt', 'w').write('["_main", "_atoi"]') + do_emcc_test('fannkuch.cpp', ['5'], 'Pfannkuchen(5) = 7.', ['-s', 'EMTERPRETIFY_BLACKLIST=@blacklist.txt']) # blacklist main and atoi with a @response file + src = open('a.out.js').read() + assert 'emterpret' not in get_func(src, '_main'), 'main is NOT emterpreted, it was blacklisted' + assert 'emterpret' not in get_func(src, '_atoi'), 'atoi is NOT emterpreted either' do_test(r''' #include diff --git a/tools/emterpretify.py b/tools/emterpretify.py index f010ba0ea6f9d..d6b7b1f00b377 100755 --- a/tools/emterpretify.py +++ b/tools/emterpretify.py @@ -17,9 +17,27 @@ LOG_CODE = os.environ.get('EMCC_LOG_EMTERPRETER_CODE') +ZERO = False + +ASYNC = False + +ASSERTIONS = False + +def handle_arg(arg): + global ZERO, ASYNC, ASSERTIONS + if '=' in arg: + l, r = arg.split('=') + if l == 'ZERO': ZERO = int(r) + elif l == 'ASYNC': ASYNC = int(r) + elif l == 'ASSERTIONS': ASSERTIONS = int(r) + return False + return True + +sys.argv = filter(handle_arg, sys.argv) + # consts -BLACKLIST = set(['_malloc', '_free', '_memcpy', '_memmove', '_memset', 'copyTempDouble', 'copyTempFloat', '_strlen', 'stackAlloc', 'setThrew', 'stackRestore', 'setTempRet0', 'getTempRet0', 'stackSave', 'runPostSets', '_emscripten_autodebug_double', '_emscripten_autodebug_float', '_emscripten_autodebug_i8', '_emscripten_autodebug_i16', '_emscripten_autodebug_i32', '_emscripten_autodebug_i64', '_strncpy', '_strcpy', '_strcat', '_saveSetjmp', '_testSetjmp', '_emscripten_replace_memory', '_bitshift64Shl', '_bitshift64Ashr', '_bitshift64Lshr']) +BLACKLIST = set(['_malloc', '_free', '_memcpy', '_memmove', '_memset', 'copyTempDouble', 'copyTempFloat', '_strlen', 'stackAlloc', 'setThrew', 'stackRestore', 'setTempRet0', 'getTempRet0', 'stackSave', 'runPostSets', '_emscripten_autodebug_double', '_emscripten_autodebug_float', '_emscripten_autodebug_i8', '_emscripten_autodebug_i16', '_emscripten_autodebug_i32', '_emscripten_autodebug_i64', '_strncpy', '_strcpy', '_strcat', '_saveSetjmp', '_testSetjmp', '_emscripten_replace_memory', '_bitshift64Shl', '_bitshift64Ashr', '_bitshift64Lshr', 'setAsyncState', 'emtStackSave']) OPCODES = [ # l, lx, ly etc - one of 256 locals 'SET', # [lx, ly, 0] lx = ly (int or float, not double) @@ -385,34 +403,63 @@ def get_coerced_access(l, s='i', unsigned=False, base='sp', offset=None): CASES[ROPCODES['GETTR0']] = get_access('lx') + ' = tempRet0;' CASES[ROPCODES['SETTR0']] = 'tempRet0 = ' + get_coerced_access('lx') + ';' +# stacktop handling: if allowing async, the very bottom will contain the function being executed, +# for stack trace reconstruction. We store [pc of function, curr pc] +# where curr pc is the current position in that function, when asyncing +# The effective sp, where locals reside, is 8 above that. + +def push_stacktop(zero): + return (' sp = EMTSTACKTOP;' if not ASYNC else ' sp = EMTSTACKTOP + 8 | 0;') if not zero else '' + +def pop_stacktop(zero): + return '//Module.print("exit");\n' + ((' EMTSTACKTOP = sp; ' if not ASYNC else 'EMTSTACKTOP = sp - 8 | 0; ') if not zero else '') + +def handle_async_pre_call(): + return 'HEAP32[sp - 4 >> 2] = pc;' if ASYNC else '' + +def handle_async_post_call(): + assert not ZERO + return 'if ((asyncState|0) == 1) { ' + pop_stacktop(zero=False) + ' return }\n' if ASYNC else '' # save pc and exit immediately if currently saving state + CASES[ROPCODES['INTCALL']] = ''' inst = HEAP32[HEAP32[pc + 4 >> 2] >> 2] | 0; // FUNC inst: ['FUNC', locals, params, which emterp] lz = (inst >>> 16) & 255; // params ly = 0; assert(((EMTSTACKTOP + 8|0) <= (EMT_STACK_MAX|0))|0); // for return value - if ((inst >>> 24) == 0) { + %s + %s while ((ly|0) < (lz|0)) { %s = %s; %s = %s; ly = ly + 1 | 0; } + %s + %s emterpret(HEAP32[pc + 4 >> 2] | 0); - } else { + %s + %s + %s = HEAP32[EMTSTACKTOP >> 2] | 0; + %s = HEAP32[EMTSTACKTOP + 4 >> 2] | 0; + pc = pc + (((4 + lz + 3) >> 2) << 2) | 0; +''' % ( + 'if ((inst >>> 24) == 0) {' if ZERO else '', + 'if ((asyncState|0) != 2) {' if ASYNC else '', + get_access('ly', base='EMTSTACKTOP', offset=8 if ASYNC else 0), get_coerced_access('HEAPU8[pc + 8 + ly >> 0]'), + get_access('ly', base='EMTSTACKTOP', offset=12 if ASYNC else 4), get_coerced_access('HEAPU8[pc + 8 + ly >> 0]', offset=4), + '}' if ASYNC else '', + handle_async_pre_call(), + handle_async_post_call(), + ('''} else { while ((ly|0) < (lz|0)) { %s = %s; %s = %s; ly = ly + 1 | 0; } emterpret_z(HEAP32[pc + 4 >> 2] | 0); - } - %s = HEAP32[EMTSTACKTOP >> 2] | 0; - %s = HEAP32[EMTSTACKTOP + 4 >> 2] | 0; - pc = pc + (((4 + lz + 3) >> 2) << 2) | 0; -''' % ( - get_access('ly', base='EMTSTACKTOP'), get_coerced_access('HEAPU8[pc + 8 + ly >> 0]'), - get_access('ly', base='EMTSTACKTOP', offset=4), get_coerced_access('HEAPU8[pc + 8 + ly >> 0]', offset=4), - get_access('ly', base=0), get_coerced_access('HEAPU8[pc + 8 + ly >> 0]'), - get_access('ly', base=0, offset=4), get_coerced_access('HEAPU8[pc + 8 + ly >> 0]', offset=4), + }''' % ( + get_access('ly', base=0), get_coerced_access('HEAPU8[pc + 8 + ly >> 0]'), + get_access('ly', base=0, offset=4), get_coerced_access('HEAPU8[pc + 8 + ly >> 0]', offset=4), + )) if ZERO else '', get_access('lx'), get_access('lx', offset=4), ) @@ -428,7 +475,7 @@ def get_coerced_access(l, s='i', unsigned=False, base='sp', offset=None): def make_emterpreter(zero=False): # return is specialized per interpreter - CASES[ROPCODES['RET']] = 'EMTSTACKTOP = sp; ' if not zero else '' + CASES[ROPCODES['RET']] = pop_stacktop(zero) CASES[ROPCODES['RET']] += 'HEAP32[EMTSTACKTOP >> 2] = ' + get_coerced_access('lx') + '; HEAP32[EMTSTACKTOP + 4 >> 2] = ' + get_coerced_access('lx', offset=4) + '; return;' # call is custom generated using information of actual call patterns, and which emterpreter this is @@ -446,6 +493,10 @@ def make_target_call(i): ret = get_access('lx', sig[0]) + ' = ' + shared.JS.make_coercion(ret, sig[0]) elif name in actual_return_types and actual_return_types[name] != 'v': ret = shared.JS.make_coercion(ret, actual_return_types[name]) # return value ignored, but need a coercion + if ASYNC: + # TODO: support return values (need to save all returns to a temp location, then use only if not saving async state) + if sig[0] == 'v': + ret = handle_async_pre_call() + ret + '; ' + handle_async_post_call() extra = len(sig) - 1 + int(function_pointer_call) # [opcode, lx, target, sig], take the usual 4. params are extra if extra > 0: ret += '; pc = pc + %d | 0' % (4*((extra+3)>>2)) @@ -479,7 +530,7 @@ def fix_case(case): return case.replace('PROCEED_WITH_PC_BUMP', 'continue').replace('PROCEED_WITHOUT_PC_BUMP', 'pc = pc - 4 | 0; continue').replace('continue; continue;', 'continue;') def process(code): - code = code.replace(' assert(', ' //assert(') + if not ASSERTIONS: code = code.replace(' assert(', ' //assert(') if zero: code = code.replace('sp + ', '') return code @@ -489,7 +540,7 @@ def process(code): lx = (inst >> 8) & 255; ly = (inst >> 16) & 255; lz = inst >>> 24; - //print([pc, inst&255, %s[inst&255], lx, ly, lz, HEAPU8[pc + 4],HEAPU8[pc + 5],HEAPU8[pc + 6],HEAPU8[pc + 7]].join(', ')); + //Module.print([pc, inst&255, %s[inst&255], lx, ly, lz, HEAPU8[pc + 4],HEAPU8[pc + 5],HEAPU8[pc + 6],HEAPU8[pc + 7]].join(', ')); ''' % (json.dumps(OPCODES)) if not INNERTERPRETER_LAST_OPCODE: @@ -523,8 +574,10 @@ def process(code): return process(r''' function emterpret%s(pc) { + //Module.print('emterpret: ' + pc + ',' + EMTSTACKTOP); pc = pc | 0; var %sinst = 0, lx = 0, ly = 0, lz = 0; +%s %s assert(((HEAPU8[pc>>0]>>>0) == %d)|0); lx = HEAPU8[pc + 1 >> 0] | 0; // num locals @@ -535,6 +588,7 @@ def process(code): %s = +0; ly = ly + 1 | 0; } +%s //print('enter func ' + [pc, HEAPU8[pc + 0],HEAPU8[pc + 1],HEAPU8[pc + 2],HEAPU8[pc + 3],HEAPU8[pc + 4],HEAPU8[pc + 5],HEAPU8[pc + 6],HEAPU8[pc + 7]].join(', ')); //var first = true; pc = pc + 4 | 0; @@ -545,11 +599,14 @@ def process(code): }''' % ( '' if not zero else '_z', 'sp = 0, ' if not zero else '', - ' sp = EMTSTACKTOP;' if not zero else '', + '' if not ASYNC else 'HEAP32[EMTSTACKTOP>>2] = pc;\n if ((asyncState|0) == 1) asyncState = 0;\n', # other code running between a save and resume can see state 1, just reset + # (optimally we should flip it to 0 at the bottom of the saving stack) + push_stacktop(zero), ROPCODES['FUNC'], - ''' EMTSTACKTOP = EMTSTACKTOP + (lx << 3) | 0; - assert(((EMTSTACKTOP|0) <= (EMT_STACK_MAX|0))|0);''' if not zero else '', + (''' EMTSTACKTOP = EMTSTACKTOP + (lx ''' + (' + 1 ' if ASYNC else '') + '''<< 3) | 0; + assert(((EMTSTACKTOP|0) <= (EMT_STACK_MAX|0))|0);\n''' + (' if ((asyncState|0) != 2) {' if ASYNC else '')) if not zero else '', get_access('ly', s='d'), + ' } else { pc = (HEAP32[sp - 4 >> 2] | 0) - 8 | 0; }' if ASYNC else '', main_loop, )) @@ -558,7 +615,15 @@ def process(code): infile = sys.argv[1] outfile = sys.argv[2] force_memfile = sys.argv[3] if len(sys.argv) >= 4 else None - extra_blacklist = json.loads(sys.argv[4]) if len(sys.argv) >= 5 else [] + + extra_blacklist = [] + if len(sys.argv) >= 5: + temp = sys.argv[4] + if temp[0] == '"': + # response file + assert temp[1] == '@' + temp = open(temp[2:-1]).read() + extra_blacklist = json.loads(temp) BLACKLIST = set(list(BLACKLIST) + extra_blacklist) @@ -599,17 +664,23 @@ def process(code): external_emterpreted_funcs = filter(lambda func: func in tabled_funcs or func in exported_funcs or func in reachable_funcs, emterpreted_funcs) # process functions, generating bytecode - shared.Building.js_optimizer(infile, ['emterpretify'], extra_info={ 'emterpretedFuncs': list(emterpreted_funcs), 'externalEmterpretedFuncs': list(external_emterpreted_funcs), 'opcodes': OPCODES, 'ropcodes': ROPCODES }, output_filename=temp, just_concat=True) + shared.Building.js_optimizer(infile, ['emterpretify'], extra_info={ 'emterpretedFuncs': list(emterpreted_funcs), 'externalEmterpretedFuncs': list(external_emterpreted_funcs), 'opcodes': OPCODES, 'ropcodes': ROPCODES, 'ASYNC': ASYNC }, output_filename=temp, just_concat=True) # load the module and modify it asm = asm_module.AsmModule(temp) + # find memfile. can be x.js.mem or x.html.mem in_mem_file = infile + '.mem' in_mem_file_base = os.path.basename(in_mem_file) out_mem_file = outfile + '.mem' out_mem_file_base = os.path.basename(out_mem_file) + if in_mem_file_base not in asm.pre_js: + in_mem_file = (infile + '.mem').replace('.js.mem', '.html.mem') + in_mem_file_base = os.path.basename(in_mem_file) + out_mem_file = (outfile + '.mem').replace('.js.mem', '.html.mem') + out_mem_file_base = os.path.basename(out_mem_file) + assert in_mem_file_base in asm.pre_js, 'we assume a mem init file for now (looked for %s)' % in_mem_file - assert in_mem_file_base in asm.pre_js, 'we assume a mem init file for now (looked for %s)' % in_mem_file if not force_memfile: asm.pre_js = asm.pre_js.replace(in_mem_file_base, out_mem_file_base) assert os.path.exists(in_mem_file), 'need to find mem file at %s' % in_mem_file @@ -792,7 +863,7 @@ def post_process_code(code): lines[i] = lines[i].replace(call, '(%s)' % (funcs[func] + code_start)) # finalize funcs JS (first line has the marker, add emterpreters right after that) - asm.funcs_js = '\n'.join([lines[0], make_emterpreter(), make_emterpreter(zero=True), '\n'.join(filter(lambda line: len(line) > 0, lines[1:]))]) + '\n' + asm.funcs_js = '\n'.join([lines[0], make_emterpreter(), make_emterpreter(zero=True) if ZERO else '', '\n'.join(filter(lambda line: len(line) > 0, lines[1:]))]) + '\n' lines = None # set up emterpreter stack top diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 523d1c6be9d46..f637699420dca 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -6128,6 +6128,7 @@ function emterpretify(ast) { var EXTERNAL_EMTERPRETED_FUNCS = set(extraInfo.externalEmterpretedFuncs); var OPCODES = extraInfo.opcodes; var ROPCODES = extraInfo.ropcodes; + var ASYNC = extraInfo.ASYNC; var RELATIVE_BRANCHES = set('BR', 'BRT', 'BRF'); var ABSOLUTE_BRANCHES = set('BRA', 'BRTA', 'BRFA'); @@ -6163,6 +6164,12 @@ function emterpretify(ast) { } function walkFunction(func) { + if (func[1] === 'emterpret') { + // we will replace the stand-in, do not emit anything for it here + func[0] = 'toplevel'; + func[1] = []; + return; + } var freeLocals = []; var maxLocal = 0; @@ -7410,7 +7417,7 @@ function emterpretify(ast) { } //if (leaf) printErr(func[1]); - var zero = leaf; // TODO: heuristics + var zero = false; // leaf; // TODO: heuristics var onlyLeavesAreZero = true; // if only leaves are zero, then we do not need to save and restore the stack XXX if this is not true, then setjmp and exceptions can fail, as cleanup is skipped! if (zero) code[3] = 1; @@ -7429,7 +7436,7 @@ function emterpretify(ast) { func[3].push(srcToStat('while ((x | 0) < ' + stackBytes + ') { HEAP32[sp + x >> 2] = HEAP32[x >> 2] | 0; x = x + 4 | 0; }')); } // copy our arguments to our stack frame - var bump = 0; // we will assert in the emterpreter itself that we did not overflow the emtstack + var bump = ASYNC ? 8 : 0; // we will assert in the emterpreter itself that we did not overflow the emtstack func[2].forEach(function(arg) { var code; switch (asmData.params[arg]) { diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 125b9733f426e..0a2d0d5924df6 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -27,6 +27,23 @@ def path_from_root(*pathelems): NATIVE_OPTIMIZER = os.environ.get('EMCC_NATIVE_OPTIMIZER') or '1' # use native optimizer by default, unless disabled by EMCC_NATIVE_OPTIMIZER=0 in the env +def find_msbuild(sln_file, make_env): + search_paths_vs2013 = [os.path.join(os.environ['ProgramFiles'], 'MSBuild/12.0/Bin/amd64'), + os.path.join(os.environ['ProgramFiles(x86)'], 'MSBuild/12.0/Bin/amd64'), + os.path.join(os.environ['ProgramFiles'], 'MSBuild/12.0/Bin'), + os.path.join(os.environ['ProgramFiles(x86)'], 'MSBuild/12.0/Bin'),] + search_paths_old = [os.path.join(os.environ["WINDIR"], 'Microsoft.NET/Framework/v4.0.30319')] + contents = open(sln_file, 'r').read() + if '# Visual Studio Express 2013' in contents or '# Visual Studio 2013' in contents: + search_paths = search_paths_vs2013 + search_paths_old + make_env['VCTargetsPath'] = os.path.join(os.environ['ProgramFiles(x86)'], 'MSBuild/Microsoft.Cpp/v4.0/V120') + else: + search_paths = search_paths_old + search_paths_vs2013 + for path in search_paths: + p = os.path.join(path, 'MSBuild.exe') + if os.path.isfile(p): return [p, make_env] + return [None, make_env] + def get_native_optimizer(): if os.environ.get('EMCC_FAST_COMPILER') == '0': return None # need fastcomp for native optimizer @@ -45,6 +62,58 @@ class NativeOptimizerCreationException(Exception): pass outs = [] errs = [] try: + def create_optimizer_cmake(): + shared.logging.debug('building native optimizer via CMake: ' + name) + output = shared.Cache.get_path(name) + shared.try_delete(output) + + if NATIVE_OPTIMIZER == '1': + cmake_build_type = 'RelWithDebInfo' + elif NATIVE_OPTIMIZER == '2': + cmake_build_type = 'Release' + elif NATIVE_OPTIMIZER == 'g': + cmake_build_type = 'Debug' + + build_path = shared.Cache.get_path('optimizer_build_' + cmake_build_type) + shared.try_delete(os.path.join(build_path, 'CMakeCache.txt')) + + log_output = None if DEBUG else subprocess.PIPE + if not os.path.exists(build_path): + os.mkdir(build_path) + + if WINDOWS: + cmake_generators = ['Visual Studio 12 Win64', 'Visual Studio 12', 'Visual Studio 11 Win64', 'Visual Studio 11', 'MinGW Makefiles', 'Unix Makefiles'] + else: + cmake_generators = ['Unix Makefiles'] + + for cmake_generator in cmake_generators: + proc = subprocess.Popen(['cmake', '-G', cmake_generator, '-DCMAKE_BUILD_TYPE='+cmake_build_type, shared.path_from_root('tools', 'optimizer')], cwd=build_path, stdin=log_output, stdout=log_output, stderr=log_output) + proc.communicate() + make_env = os.environ.copy() + if proc.returncode == 0: + if 'Visual Studio' in cmake_generator: + ret = find_msbuild(os.path.join(build_path, 'asmjs_optimizer.sln'), make_env) + make = [ret[0], '/t:Build', '/p:Configuration='+cmake_build_type, '/nologo', '/verbosity:minimal', 'asmjs_optimizer.sln'] + make_env = ret[1] + elif 'MinGW' in cmake_generator: + make = ['mingw32-make'] + else: + make = ['make'] + + proc = subprocess.Popen(make, cwd=build_path, stdin=log_output, stdout=log_output, stderr=log_output, env=make_env) + proc.communicate() + if proc.returncode == 0: + if WINDOWS and 'Visual Studio' in cmake_generator: + shutil.copyfile(os.path.join(build_path, cmake_build_type, 'optimizer.exe'), output) + else: + shutil.copyfile(os.path.join(build_path, 'optimizer'), output) + return output + else: + shared.try_delete(os.path.join(build_path, 'CMakeCache.txt')) + # Proceed to next iteration of the loop to try next possible CMake generator. + + raise NativeOptimizerCreationException() + def create_optimizer(): shared.logging.debug('building native optimizer: ' + name) output = shared.Cache.get_path(name) @@ -63,7 +132,12 @@ def create_optimizer(): if compiler == shared.CLANG: raise # otherwise, OSError is likely due to g++ or clang++ not being in the path if os.path.exists(output): return output raise NativeOptimizerCreationException() - return shared.Cache.get(name, create_optimizer, extension='exe') + + use_cmake_to_configure = WINDOWS # Currently only Windows uses CMake to drive the optimizer build, but set this to True to use on other platforms as well. + if use_cmake_to_configure: + return shared.Cache.get(name, create_optimizer_cmake, extension='exe') + else: + return shared.Cache.get(name, create_optimizer, extension='exe') except NativeOptimizerCreationException, e: shared.logging.debug('failed to build native optimizer') handle_build_errors(outs, errs) diff --git a/tools/optimizer/optimizer.cpp b/tools/optimizer/optimizer.cpp index ef006795c1883..ddfea32e2b74e 100644 --- a/tools/optimizer/optimizer.cpp +++ b/tools/optimizer/optimizer.cpp @@ -3346,7 +3346,10 @@ void registerizeHarder(Ref ast) { sortedJunctionVariables.push_back(pair.first); } std::sort(sortedJunctionVariables.begin(), sortedJunctionVariables.end(), [&](const IString name1, const IString name2) { - //return strcmp(name1.str, name2.str) > 0;// XXX junctionVariables[name1].conf.size() > junctionVariables[name2].conf.size(); + //// sort params first + //if (asmData.isParam(name1) && !asmData.isParam(name2)) return true; + //if (!asmData.isParam(name1) && asmData.isParam(name2)) return false; + // sort by # of conflicts if (junctionVariables[name1].conf.size() < junctionVariables[name2].conf.size()) return true; if (junctionVariables[name1].conf.size() == junctionVariables[name2].conf.size()) return name1 < name2; return false; diff --git a/tools/optimizer/simple_ast.h b/tools/optimizer/simple_ast.h index 452b5680e9fbd..9650586eb7deb 100644 --- a/tools/optimizer/simple_ast.h +++ b/tools/optimizer/simple_ast.h @@ -1105,6 +1105,11 @@ struct JSPrinter { emit(';'); } + static bool ifHasElse(Ref node) { + assert(node[0] == IF); + return node->size() >= 4 && !!node[3]; + } + void printIf(Ref node) { emit("if"); safeSpace(); @@ -1113,8 +1118,26 @@ struct JSPrinter { emit(')'); space(); // special case: we need braces to save us from ambiguity, if () { if () } else. otherwise else binds to inner if - bool hasElse = node->size() >= 4 && !!node[3]; - bool needBraces = node[2][0] == IF && (node[2]->size() == 3 || !node[2][3]) && hasElse; + // also need to recurse for if () { if () { } else { if () } else + // (note that this is only a problem if the if body has a single element in it, not a block or such, as then + // the block would be braced) + bool needBraces = false; + bool hasElse = ifHasElse(node); + if (hasElse) { + Ref child = node[2]; + while (child[0] == IF) { + Ref last = ifHasElse(child) ? child[3] : child[2]; + if (last[0] == IF) { + child = last; + continue; + } + // we are at the top, the one dangerous to be confused with us + if (!ifHasElse(child)) { + needBraces = true; + } + break; + } + } if (needBraces) { emit('{'); indent++; diff --git a/tools/ports/sdl.py b/tools/ports/sdl.py index cc77c6f6461fc..bce79f30b35aa 100644 --- a/tools/ports/sdl.py +++ b/tools/ports/sdl.py @@ -1,6 +1,6 @@ import os, shutil, logging -VERSION = 2 +VERSION = 3 def get_with_configure(ports, settings, shared): # not currently used; no real need for configure on emscripten users' machines! if settings.USE_SDL == 2: diff --git a/tools/system_libs.py b/tools/system_libs.py index db0d7f8792360..86a2ef2117a41 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -788,6 +788,36 @@ class State: unpacked = False def retrieve(): + # if EMCC_LOCAL_PORTS is set, we use a local directory as our ports. This is useful + # for testing. This env var should be in format + # name=dir|subdir,name=dir|subdir + # e.g. + # sdl2=/home/username/dev/ports/SDL2|SDL2-master + # so you could run + # EMCC_LOCAL_PORTS="sdl2=/home/username/dev/ports/SDL2|SDL2-master" ./tests/runner.py browser.test_sdl2_mouse + local_ports = os.environ.get('EMCC_LOCAL_PORTS') + if local_ports: + local_ports = map(lambda pair: pair.split('='), local_ports.split(',')) + for local in local_ports: + if name == local[0]: + path, subdir = local[1].split('|') + logging.warning('grabbing local port: ' + name + ' from ' + path + ', into ' + subdir) + # zip up the directory, so it looks the same as if we downloaded a zip from the remote server + import zipfile + z = zipfile.ZipFile(fullname + '.zip', 'w') + def add_dir(p): + for f in os.listdir(p): + full = os.path.join(p, f) + if os.path.isdir(full): + add_dir(full) + else: + if not f.startswith('.'): # ignore hidden files, including .git/ etc. + z.write(full, os.path.join(subdir, os.path.relpath(full, path))) + add_dir(path) + z.close() + State.retrieved = True + return + # retrieve from remote server logging.warning('retrieving port: ' + name + ' from ' + url) import urllib2 f = urllib2.urlopen(url)