diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-11-13 20:45:14 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-11-13 20:45:14 -0800 |
commit | 5b09129a27a5ee02f191c50f894de0e77237d392 (patch) | |
tree | bd508e9bf570765b9d89cea2f6090ceec3f6c947 | |
parent | 811e8840097e7a53a35dd3703970e5eaa19f01fa (diff) |
simplify typed array code, support for .set() on typed arrays, and remove option to fallback from typed arrays
-rw-r--r-- | src/parseTools.js | 47 | ||||
-rw-r--r-- | src/preamble.js | 40 | ||||
-rw-r--r-- | tests/runner.py | 4 |
3 files changed, 41 insertions, 50 deletions
diff --git a/src/parseTools.js b/src/parseTools.js index 6c9494a6..6f71e75d 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -934,7 +934,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore) { } } -var UNROLL_LOOP_LIMIT = 8; +var UNROLL_LOOP_MAX = 5; function makeSetValues(ptr, pos, value, type, num) { function safety(where) { @@ -943,7 +943,7 @@ function makeSetValues(ptr, pos, value, type, num) { } if (USE_TYPED_ARRAYS in set(0, 1)) { if (isNumber(num)) { - if (num < UNROLL_LOOP_LIMIT) { + if (parseInt(num) <= UNROLL_LOOP_MAX) { return range(num).map(function(i) { return makeSetValue(ptr, getFastValue(pos, '+', i), value, type); }).join('; '); @@ -980,6 +980,8 @@ function makeSetValues(ptr, pos, value, type, num) { } } +var TYPED_ARRAY_SET_MIN = Infinity; // .set() as memcpy seems to just slow us down + function makeCopyValues(dest, src, num, type, modifier) { function safety(to, from) { to = to || (dest + '+' + 'mcpi'); @@ -988,7 +990,7 @@ function makeCopyValues(dest, src, num, type, modifier) { } if (USE_TYPED_ARRAYS <= 1) { if (isNumber(num)) { - if (num < UNROLL_LOOP_LIMIT) { + if (parseInt(num) <= UNROLL_LOOP_MAX) { return range(num).map(function(i) { return type !== 'null' ? makeSetValue(dest, i, makeGetValue(src, i, type) + (modifier || ''), type) : // Null is special-cased: We copy over all heaps @@ -1012,34 +1014,45 @@ function makeCopyValues(dest, src, num, type, modifier) { ' HEAP[mcpi_d] = HEAP[mcpi_s];\n' + '}'; } else { // USE_TYPED_ARRAYS == 1 + if (isNumber(num) && parseInt(num) >= TYPED_ARRAY_SET_MIN) { + return 'IHEAP.set(IHEAP.subarray(' + src + ',' + src + '+' + num + '), ' + dest + '); ' + + 'FHEAP.set(FHEAP.subarray(' + src + ',' + src + '+' + num + '), ' + dest + ')'; + } return 'for (var mcpi_s=' + src + ',mcpi_e=' + src + '+' + num + ',mcpi_d=' + dest + '; mcpi_s<mcpi_e; mcpi_s++, mcpi_d++) {\n' + ' IHEAP[mcpi_d] = IHEAP[mcpi_s];' + (USE_FHEAP ? ' FHEAP[mcpi_d] = FHEAP[mcpi_s];' : '') + '\n' + '}'; } } else { // USE_TYPED_ARRAYS == 2 - return '' + - 'var src, dest, stop, stop4, fast;\n' + + var ret = '' + + 'var src, dest, stop, stop4;\n' + 'src = ' + src + ';\n' + 'dest = ' + dest + ';\n' + 'stop = src + ' + num + ';\n' + 'if ((dest%4) == (src%4) && ' + num + ' > 8) {\n' + ' while (src%4 !== 0 && src < stop) {\n' + ' ' + safety('dest', 'src') + '; HEAP8[dest++] = HEAP8[src++];\n' + - ' }\n' + - ' src >>= 2;\n' + - ' dest >>= 2;\n' + - ' stop4 = stop >> 2;\n' + - ' while (src < stop4) {\n' + - safety('(dest<<2)+0', '(src<<2)+0') + ';' + safety('(dest<<2)+1', '(src<<2)+1') + ';' + - safety('(dest<<2)+2', '(src<<2)+2') + ';' + safety('(dest<<2)+3', '(src<<2)+3') + (SAFE_HEAP ? ';\n' : '') + - ' HEAP32[dest++] = HEAP32[src++];\n' + // this is the fast inner loop we try hard to stay in - ' }\n' + - ' src <<= 2;\n' + - ' dest <<= 2;\n' + - '}' + + ' }\n'; + if (SAFE_HEAP || !(isNumber(num) && parseInt(num) >= TYPED_ARRAY_SET_MIN)) { + ret += ' src >>= 2;\n' + + ' dest >>= 2;\n' + + ' stop4 = stop >> 2;\n' + + ' while (src < stop4) {\n' + + safety('(dest<<2)+0', '(src<<2)+0') + ';' + safety('(dest<<2)+1', '(src<<2)+1') + ';' + + safety('(dest<<2)+2', '(src<<2)+2') + ';' + safety('(dest<<2)+3', '(src<<2)+3') + (SAFE_HEAP ? ';\n' : '') + + ' HEAP32[dest++] = HEAP32[src++];\n' + + ' }\n' + + ' src <<= 2;\n' + + ' dest <<= 2;\n'; + } else { + ret += ' var src4 = src >> 2, stop4 = stop >> 2, num4 = (stop4 - src4) << 2;\n' + + ' HEAP32.set(HEAP32.subarray(src4, stop4), dest >> 2);\n' + + ' src += num4; dest += num4;\n'; + } + ret += '}' + 'while (src < stop) {\n' + ' ' + safety('dest', 'src') + '; HEAP8[dest++] = HEAP8[src++];\n' + '}'; + return ret; } return null; } diff --git a/src/preamble.js b/src/preamble.js index 45513942..7aa07cc1 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -537,18 +537,15 @@ var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32; var STACK_ROOT, STACKTOP, STACK_MAX; var STATICTOP; -var HAS_TYPED_ARRAYS = false; var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || {{{ TOTAL_MEMORY }}}; var FAST_MEMORY = Module['FAST_MEMORY'] || {{{ FAST_MEMORY }}}; // Initialize the runtime's memory #if USE_TYPED_ARRAYS -HAS_TYPED_ARRAYS = false; -try { - HAS_TYPED_ARRAYS = !!Int32Array && !!Float64Array && !!(new Int32Array(1)['subarray']); // check for full engine support (use string 'subarray' to avoid closure compiler confusion) -} catch(e) {} +// check for full engine support (use string 'subarray' to avoid closure compiler confusion) + assert(!!Int32Array && !!Float64Array && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']), + 'Cannot fallback to non-typed array case: Code is too specialized'); -if (HAS_TYPED_ARRAYS) { #if USE_TYPED_ARRAYS == 1 HEAP = IHEAP = new Int32Array(TOTAL_MEMORY); #if USE_FHEAP @@ -569,24 +566,13 @@ if (HAS_TYPED_ARRAYS) { HEAP32[0] = 255; assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system'); #endif -} else -#endif -{ +#else // Make sure that our HEAP is implemented as a flat array. HEAP = new Array(TOTAL_MEMORY); for (var i = 0; i < FAST_MEMORY; i++) { HEAP[i] = 0; // XXX We do *not* use {{| makeSetValue(0, 'i', 0, 'null') |}} here, since this is done just to optimize runtime speed } -#if USE_TYPED_ARRAYS == 1 - IHEAP = HEAP; -#if USE_FHEAP - FHEAP = HEAP; -#endif -#endif -#if USE_TYPED_ARRAYS == 2 - abort('Cannot fallback to non-typed array case in USE_TYPED_ARRAYS == 2: Code is too specialized'); #endif -} var base = intArrayFromString('(null)'); // So printing %s of NULL gives '(null)' // Also this ensures we leave 0 as an invalid address, 'NULL' @@ -637,22 +623,14 @@ function __shutdownRuntime__() { // Copies a list of num items on the HEAP into a // a normal JavaScript array of numbers function Array_copy(ptr, num) { - // TODO: In the SAFE_HEAP case, do some reading here, for debugging purposes - currently this is an 'unnoticed read'. #if USE_TYPED_ARRAYS == 1 - if (HAS_TYPED_ARRAYS) { - return Array.prototype.slice.call(IHEAP.subarray(ptr, ptr+num)); // Make a normal array out of the typed 'view' - // Consider making a typed array here, for speed? - } else { - return IHEAP.slice(ptr, ptr+num); - } + // TODO: In the SAFE_HEAP case, do some reading here, for debugging purposes - currently this is an 'unnoticed read'. + return Array.prototype.slice.call(IHEAP.subarray(ptr, ptr+num)); // Make a normal array out of the typed 'view' + // Consider making a typed array here, for speed? #endif #if USE_TYPED_ARRAYS == 2 - if (HAS_TYPED_ARRAYS) { - return Array.prototype.slice.call(HEAP8.subarray(ptr, ptr+num)); // Make a normal array out of the typed 'view' - // Consider making a typed array here, for speed? - } else { - return HEAP8.slice(ptr, ptr+num); - } + return Array.prototype.slice.call(HEAP8.subarray(ptr, ptr+num)); // Make a normal array out of the typed 'view' + // Consider making a typed array here, for speed? #endif return HEAP.slice(ptr, ptr+num); } diff --git a/tests/runner.py b/tests/runner.py index 36226769..6ab84708 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -243,8 +243,8 @@ if 'benchmark' not in str(sys.argv): # Run in both JavaScript engines, if optimizing - significant differences there (typed arrays) if js_engines is None: js_engines = [SPIDERMONKEY_ENGINE, V8_ENGINE] - if Settings.USE_TYPED_ARRAYS == 2: - js_engines = [SPIDERMONKEY_ENGINE] # when oh when will v8 support typed arrays in the console + if Settings.USE_TYPED_ARRAYS: + js_engines = [SPIDERMONKEY_ENGINE] # V8 issue 1822 js_engines = filter(lambda engine: os.path.exists(engine[0]), js_engines) assert len(js_engines) > 0, 'No JS engine present to run this test with. Check ~/.emscripten and the paths therein.' for engine in js_engines: |