diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-06-04 20:43:04 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-06-04 20:43:04 -0700 |
commit | c5d4ba79fab0ad46dec71eaa8c4c1d47cca169ee (patch) | |
tree | 62041c1b8acdf9cba3ccd1ab8d95c3869134c04a | |
parent | 304221e18f276e5bd539f9b0238c854274074021 (diff) |
optimize Pointer_make (both input size and processing time)
-rw-r--r-- | src/library.js | 2 | ||||
-rw-r--r-- | src/parseTools.js | 28 | ||||
-rw-r--r-- | src/preamble.js | 56 |
3 files changed, 67 insertions, 19 deletions
diff --git a/src/library.js b/src/library.js index 74918a95..23bda6ce 100644 --- a/src/library.js +++ b/src/library.js @@ -900,7 +900,7 @@ var Library = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0 ]; - me.ret = Pointer_make([Pointer_make(values, 0, ALLOC_STATIC, 'void*')+256], 0, ALLOC_STATIC, 'i16'); + me.ret = Pointer_make([Pointer_make(values, 0, ALLOC_STATIC, 'i16')+256], 0, ALLOC_STATIC, 'void*'); #if USE_TYPED_ARRAYS == 0 assert(HEAP[HEAP[me.ret]] == 2); assert(HEAP[HEAP[me.ret]-2] == 0); diff --git a/src/parseTools.js b/src/parseTools.js index 4db740db..6ae0e5d3 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -585,7 +585,7 @@ function generateStructTypes(type) { ret = ret.concat(zeros(typeData.flatIndexes[i+1] - ret.length)); } } - return ret; + return ret.concat(zeros(typeData.flatSize - ret.length)); } // Flow blocks @@ -819,7 +819,31 @@ function makePointer(slab, pos, allocator, type) { assert(type, 'makePointer requires type info'); if (slab.substr(0, 4) === 'HEAP' || (USE_TYPED_ARRAYS == 1 && slab in set('IHEAP', 'FHEAP'))) return pos; var types = generateStructTypes(type); - if (dedup(types).length === 1) types = types[0]; + + // compress type info and data if possible + var de; + try { + // compress all-zeros into a number (which will become zeros(..)). + // note that we cannot always eval the slab, e.g., if it contains ident,0,0 etc. In that case, no compression TODO: ensure we get arrays here, not str + var evaled = typeof slab === 'string' ? eval(slab) : slab; + de = dedup(evaled); + if (de.length === 1 && de[0] === 0) { + slab = evaled.length; + } + // TODO: if not all zeros, at least filter out items with type === 0. requires cleverness to know how to skip at runtime though. also + // be careful of structure padding + } catch(e){} + de = dedup(types); + if (de.length === 1) { + types = de[0]; + } else if (de.length === 2 && typeof slab === 'number') { + // If slab is all zeros, we can compress types even if we have i32,0,0,0,i32,0,0,0 etc. - we do not need the zeros + de = de.filter(function(x) { return x !== 0 }); + if (de.length === 1) { + types = de[0]; + } + } + return 'Pointer_make(' + slab + ', ' + (pos ? pos : 0) + (allocator ? ', ' + allocator : '') + ', ' + JSON.stringify(types) + ')'; diff --git a/src/preamble.js b/src/preamble.js index 20a645e3..9314f192 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -262,32 +262,56 @@ function Pointer_make(slab, pos, allocator, types) { pos = pos ? pos : 0; assert(pos === 0); // TODO: remove 'pos' if (slab === HEAP) return pos; - var size = slab.length; - - var i; -#if ASSERTIONS - for (i = 0; i < size; i++) { - if (slab[i] === undefined) { - throw 'Invalid element in slab at ' + new Error().stack; // This can be caught, and you can try again to allocate later, see globalFuncs in run() - } + var zeroinit, size; + if (typeof slab === 'number') { + zeroinit = true; + size = slab; + } else { + zeroinit = false; + size = slab.length; } -#endif // Finalize var ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc][allocator ? allocator : ALLOC_STATIC](Math.max(size, 1)); - var type = typeof types === 'string' ? types : null; + var singleType = typeof types === 'string' ? types : null; - for (i = 0; i < size; i++) { - var curr = slab[i]; + var i = 0, type; + while (i < size) { + var curr = zeroinit ? 0 : slab[i]; if (typeof curr === 'function') { curr = Runtime.getFunctionIndex(curr); } - if (type || types[i]) { - {{{ makeSetValue(0, 'ret+i', 'curr', '#type || types[i]') }}} + type = singleType || types[i]; + if (type === 0) { + i++; + continue; } +#if ASSERTIONS + assert(type, 'Must know what type to store in Pointer_make!'); +#endif + + if (type === 'i8') { + {{{ makeSetValue(0, 'ret+i', 'curr', 'i8') }}} + i += {{{ getNativeFieldSize('i8', true) }}}; + } else if (type === 'i16') { + {{{ makeSetValue(0, 'ret+i', 'curr', 'i16') }}} + i += {{{ getNativeFieldSize('i16', true) }}}; + } else if (type === 'i32' || type[type.length-1] === '*') { // hardcoded pointers as 32-bit + {{{ makeSetValue(0, 'ret+i', 'curr', 'i32') }}} + i += {{{ getNativeFieldSize('i32', true) }}}; + } else if (type === 'i64') { + {{{ makeSetValue(0, 'ret+i', 'curr', 'i64') }}} + i += {{{ getNativeFieldSize('i64', true) }}}; + } else if (type === 'float') { + {{{ makeSetValue(0, 'ret+i', 'curr', 'float') }}} + i += {{{ getNativeFieldSize('float', true) }}}; + } else if (type === 'double') { + {{{ makeSetValue(0, 'ret+i', 'curr', 'double') }}} + i += {{{ getNativeFieldSize('double', true) }}}; + } else throw 'invalid type for Pointer_make: ' + type; } return ret; @@ -488,8 +512,8 @@ function intArrayToString(array) { return ret; } -var unSign = {{{ unSign.toString() }}} -var reSign = {{{ reSign.toString() }}} +{{{ unSign }}} +{{{ reSign }}} // Use console read if available, otherwise we are in a browser, use an XHR if (!this['read']) { |