aboutsummaryrefslogtreecommitdiff
path: root/src/parseTools.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/parseTools.js')
-rw-r--r--src/parseTools.js170
1 files changed, 62 insertions, 108 deletions
diff --git a/src/parseTools.js b/src/parseTools.js
index c0a1879a..719fe458 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1030,130 +1030,84 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe)
}
}
+var SEEK_OPTIMAL_ALIGN_MIN = 40;
var UNROLL_LOOP_MAX = 5;
-var ZERO_ONE = set(0, 1);
-
-function makeSetValues(ptr, pos, value, type, num) {
- function safety(where) {
- where = where || getFastValue(ptr, '+', pos) + '+mspi';
- return ';' + (SAFE_HEAP ? 'SAFE_HEAP_ACCESS(' + where + ', ' + type + ', 1)' : '');
+function makeSetValues(ptr, pos, value, type, num, align) {
+ function unroll(type, num, jump) {
+ jump = jump || 1;
+ return range(num).map(function(i) {
+ return makeSetValue(ptr, getFastValue(pos, '+', i*jump), value, type);
+ }).join('; ');
}
- if (USE_TYPED_ARRAYS in ZERO_ONE) {
- if (isNumber(num)) {
- if (parseInt(num) <= UNROLL_LOOP_MAX) {
- return range(num).map(function(i) {
- return makeSetValue(ptr, getFastValue(pos, '+', i), value, type);
- }).join('; ');
- }
+ if (USE_TYPED_ARRAYS <= 1) {
+ if (isNumber(num) && parseInt(num) <= UNROLL_LOOP_MAX) {
+ return unroll(type, num);
}
- return 'for (var mspi = 0; mspi < ' + num + '; mspi++) {\n' +
- makeSetValue(ptr, getFastValue(pos, '+', 'mspi'), value, type) + '\n}';
+ return 'for (var $$i = 0; $$i < ' + num + '; $$i++) {\n' +
+ makeSetValue(ptr, getFastValue(pos, '+', '$$i'), value, type) + '\n}';
} else { // USE_TYPED_ARRAYS == 2
-/*
- return 'for (var mspi = 0; mspi < ' + num + '; mspi++) {\n' +
- ' HEAP8[' + getFastValue(ptr, '+', pos) + '+mspi] = ' + value + safety() + '\n}';
-*/
- return '' +
- 'var dest_, stop_, stop4_, fast_, value_;\n' +
- 'dest_ = ' + getFastValue(ptr, '+', pos) + ';\n' +
- 'stop_ = dest_ + ' + num + ';\n' +
- 'value_ = ' + value + ';\n' +
- 'if (value_ < 0) value_ += 256;\n' +
- 'value_ = value_ + (value_<<8) + (value_<<16) + (value_*16777216);\n' +
- 'while (dest_%4 !== 0 && dest_ < stop_) {\n' +
- ' ' + safety('dest_') + '; HEAP8[dest_++] = ' + value + ';\n' +
- '}\n' +
- 'dest_ >>= 2;\n' +
- 'stop4_ = stop_ >> 2;\n' +
- 'while (dest_ < 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_++] = value_;\n' + // this is the fast inner loop we try hard to stay in
- '}\n' +
- 'dest_ <<= 2;\n' +
- 'while (dest_ < stop_) {\n' +
- ' ' + safety('dest_') + '; HEAP8[dest_++] = ' + value + ';\n' +
- '}'
+ // If we don't know how to handle this at compile-time, or handling it is best done in a large amount of code, call memset
+ if (!isNumber(num) || (align < 4 && parseInt(num) >= SEEK_OPTIMAL_ALIGN_MIN)) {
+ return '_memset(' + getFastValue(ptr, '+', pos) + ', ' + value + ', ' + num + ', ' + align + ')';
+ }
+ num = parseInt(num);
+ var ret = [];
+ [4, 2, 1].forEach(function(possibleAlign) {
+ if (num == 0) return;
+ if (align >= possibleAlign) {
+ if (num <= UNROLL_LOOP_MAX*possibleAlign) {
+ ret.push(unroll('i' + (possibleAlign*8), Math.floor(num/possibleAlign), possibleAlign));
+ } else {
+ ret.push('for (var $$i = 0, $$base = ' + getFastValue(ptr, '+', pos) + (possibleAlign > 1 ? '>>' + log2(possibleAlign) : '') +
+ '; $$i < ' + Math.floor(num/possibleAlign) + '; $$i++) {\n' +
+ ' HEAP' + (possibleAlign*8) + '[$$base+$$i] = ' + value + '\n}');
+ }
+ num %= possibleAlign;
+ }
+ });
+ return ret.join('; ');
}
}
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');
- from = from || (src + '+' + 'mcpi');
- return (SAFE_HEAP ? 'SAFE_HEAP_COPY_HISTORY(' + to + ', ' + from + ')' : '');
+function makeCopyValues(dest, src, num, type, modifier, align) {
+ function unroll(type, num, jump) {
+ jump = jump || 1;
+ return range(num).map(function(i) {
+ return makeSetValue(dest, i*jump, makeGetValue(src, i*jump, type), type);
+ }).join('; ');
}
if (USE_TYPED_ARRAYS <= 1) {
- if (isNumber(num)) {
- 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
- makeGetSlabs(dest, 'null', true).map(function(slab) {
- return slab + '[' + getFastValue(dest, '+', i) + ']=' + slab + '[' + getFastValue(src, '+', i) + ']';
- }).join('; ') + '; ' + safety(dest + '+' + i, src + '+' + i)
- }).join('; ');
- }
- }
- if (SAFE_HEAP) {
- return 'for (var mcpi = 0; mcpi < ' + num + '; mcpi++) {\n' +
- (type !== 'null' ? makeSetValue(dest, 'mcpi', makeGetValue(src, 'mcpi', type) + (modifier || ''), type)
- : // Null is special-cased: We copy over all heaps
- makeGetSlabs(dest, 'null', true).map(function(slab) {
- return slab + '[' + dest + '+mcpi]=' + slab + '[' + src + '+mcpi]'
- }).join('; ') + '; ' + safety()
- ) + '\n' + '}';
- }
- if (USE_TYPED_ARRAYS == 0) {
- return 'for (var mcpi_s=' + src + ',mcpi_e=' + src + '+' + num + ',mcpi_d=' + dest + '; mcpi_s<mcpi_e; mcpi_s++, mcpi_d++) {\n' +
- ' 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' +
- '}';
+ if (isNumber(num) && parseInt(num) <= UNROLL_LOOP_MAX) {
+ return unroll(type, num);
}
+ return 'for (var $$i = 0; $$i < ' + num + '; $$i++) {\n' +
+ makeSetValue(dest, '$$i', makeGetValue(src, i*jump, type), type) + '\n}';
} else { // USE_TYPED_ARRAYS == 2
- // TODO: optimize, add unrolling, etc.
- 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';
- 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';
+ // If we don't know how to handle this at compile-time, or handling it is best done in a large amount of code, call memset
+ if (!isNumber(num) || (align < 4 && parseInt(num) >= SEEK_OPTIMAL_ALIGN_MIN)) {
+ return '_memcpy(' + dest + ', ' + src + ', ' + num + ', ' + align + ')';
}
- ret += '}' +
- 'while (src_ < stop_) {\n' +
- ' ' + safety('dest_', 'src_') + '; HEAP8[dest_++] = HEAP8[src_++];\n' +
- '}';
- return ret;
+ num = parseInt(num);
+ var ret = [];
+ [4, 2, 1].forEach(function(possibleAlign) {
+ if (num == 0) return;
+ if (align >= possibleAlign) {
+ if (num <= UNROLL_LOOP_MAX*possibleAlign) {
+ ret.push(unroll('i' + (possibleAlign*8), Math.floor(num/possibleAlign), possibleAlign));
+ } else {
+ ret.push('for (var $$i = 0, $$src = ' + src + (possibleAlign > 1 ? '>>' + log2(possibleAlign) : '') + ', ' +
+ '$$dest = ' + dest + (possibleAlign > 1 ? '>>' + log2(possibleAlign) : '') + '; ' +
+ '$$i < ' + Math.floor(num/possibleAlign) + '; $$i++) {\n' +
+ ' HEAP' + (possibleAlign*8) + '[$$dest+$$i] = HEAP' + (possibleAlign*8) + '[$$src+$$i]\n}');
+ }
+ num %= possibleAlign;
+ }
+ });
+ return ret.join('; ');
}
- return null;
}
var PLUS_MUL = set('+', '*');