diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.js | 59 | ||||
-rw-r--r--[-rwxr-xr-x] | src/embind/embind.js | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/embind/emval.js | 0 | ||||
-rw-r--r-- | src/library.js | 131 | ||||
-rw-r--r-- | src/modules.js | 3 | ||||
-rw-r--r-- | src/settings.js | 4 |
6 files changed, 143 insertions, 54 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 03d44cb7..3f9025da 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -99,7 +99,66 @@ function analyzer(data, sidePass) { } } delete item.items; + this.forwardItem(item, 'CastAway'); + } + }); + + // CastAway - try to remove bitcasts of double to i64, which LLVM sometimes generates unnecessarily + // (load a double, convert to i64, use as i64). + // We optimize this by checking if the value is later converted to an i64. If so we create a shadow + // variable that is a load of an i64, and use that in those places. (As SSA, this is valid, and + // variable elimination later will remove the double load if it is no longer needed.) + // + substrate.addActor('CastAway', { + processItem: function(item) { this.forwardItem(item, 'Legalizer'); + if (USE_TYPED_ARRAYS != 2) return; + + item.functions.forEach(function(func) { + var changed = false; + func.labels.forEach(function(label) { + var doubleVars = {}; + var lines = label.lines; + var i = 0; + while (i < lines.length) { + var line = lines[i]; + if (line.intertype == 'load' && line.type == 'double') { + doubleVars[line.assignTo] = i; + } else if (line.intertype == 'bitcast' && line.type == 'i64' && line.ident in doubleVars) { + // this is a bitcast of a loaded double into an i64. create shadow var + var shadow = line.ident + '$$i64doubleSHADOW'; + var loadI = doubleVars[line.ident]; + var load = lines[loadI]; + if (load.pointer.intertype != 'value') { i++; continue } // TODO + // create shadow + lines.splice(loadI + 1, 0, { // this element will be legalized in the next phase + tokens: null, + indent: 2, + lineNum: load.lineNum + 0.5, + assignTo: shadow, + intertype: 'load', + pointerType: 'i64*', + type: 'i64', + valueType: 'i64', + pointer: { + intertype: 'value', + ident: load.pointer.ident, + type: 'i64*' + }, + align: load.align, + ident: load.ident + }); + // use shadow + line.params[0].ident = shadow; + line.params[0].type = 'i64'; + line.type2 = 'i64'; + // note: no need to update func.lines, it is generated in a later pass + i++; + } + i++; + } + }); + }); } }); diff --git a/src/embind/embind.js b/src/embind/embind.js index cadee700..cadee700 100755..100644 --- a/src/embind/embind.js +++ b/src/embind/embind.js diff --git a/src/embind/emval.js b/src/embind/emval.js index c02ffa92..c02ffa92 100755..100644 --- a/src/embind/emval.js +++ b/src/embind/emval.js diff --git a/src/library.js b/src/library.js index cfe83c6e..6bfb49ef 100644 --- a/src/library.js +++ b/src/library.js @@ -296,74 +296,97 @@ LibraryManager.library = { if (typeof XMLHttpRequest !== 'undefined') { if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. - var LazyUint8Array = function(chunkSize, length) { - this.length = length; - this.chunkSize = chunkSize; + var LazyUint8Array = function() { + this.lengthKnown = false; this.chunks = []; // Loaded chunks. Index is the chunk number } LazyUint8Array.prototype.get = function(idx) { if (idx > this.length-1 || idx < 0) { return undefined; } - var chunkOffset = idx % chunkSize; - var chunkNum = Math.floor(idx / chunkSize); + var chunkOffset = idx % this.chunkSize; + var chunkNum = Math.floor(idx / this.chunkSize); return this.getter(chunkNum)[chunkOffset]; } LazyUint8Array.prototype.setDataGetter = function(getter) { this.getter = getter; } - - // Find length - var xhr = new XMLHttpRequest(); - xhr.open('HEAD', url, false); - xhr.send(null); - if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); - var datalength = Number(xhr.getResponseHeader("Content-length")); - var header; - var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; + + LazyUint8Array.prototype.cacheLength = function() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + var datalength = Number(xhr.getResponseHeader("Content-length")); + var header; + var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; #if SMALL_XHR_CHUNKS - var chunkSize = 1024; // Chunk size in bytes + var chunkSize = 1024; // Chunk size in bytes #else - var chunkSize = 1024*1024; // Chunk size in bytes + var chunkSize = 1024*1024; // Chunk size in bytes #endif - if (!hasByteServing) chunkSize = datalength; - - // Function to get a range from the remote URL. - var doXHR = (function(from, to) { - if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); - if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); - - // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. - var xhr = new XMLHttpRequest(); - xhr.open('GET', url, false); - if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); - - // Some hints to the browser that we want binary data. - if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer'; - if (xhr.overrideMimeType) { - xhr.overrideMimeType('text/plain; charset=x-user-defined'); - } + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (function(from, to) { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer'; + if (xhr.overrideMimeType) { + xhr.overrideMimeType('text/plain; charset=x-user-defined'); + } + + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(xhr.response || []); + } else { + return intArrayFromString(xhr.responseText || '', true); + } + }); + var lazyArray = this; + lazyArray.setDataGetter(function(chunkNum) { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); + return lazyArray.chunks[chunkNum]; + }); + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } - xhr.send(null); - if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); - if (xhr.response !== undefined) { - return new Uint8Array(xhr.response || []); - } else { - return intArrayFromString(xhr.responseText || '', true); - } + var lazyArray = new LazyUint8Array(); + Object.defineProperty(lazyArray, "length", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } }); - - var lazyArray = new LazyUint8Array(chunkSize, datalength); - lazyArray.setDataGetter(function(chunkNum) { - var start = chunkNum * lazyArray.chunkSize; - var end = (chunkNum+1) * lazyArray.chunkSize - 1; // including this byte - end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block - if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { - lazyArray.chunks[chunkNum] = doXHR(start, end); - } - if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); - return lazyArray.chunks[chunkNum]; + Object.defineProperty(lazyArray, "chunkSize", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } }); + var properties = { isDevice: false, contents: lazyArray }; } else { var properties = { isDevice: false, url: url }; @@ -2465,9 +2488,15 @@ LibraryManager.library = { __scanString.whiteSpace[{{{ charCode(' ') }}}] = 1; __scanString.whiteSpace[{{{ charCode('\t') }}}] = 1; __scanString.whiteSpace[{{{ charCode('\n') }}}] = 1; + __scanString.whiteSpace[{{{ charCode('\v') }}}] = 1; + __scanString.whiteSpace[{{{ charCode('\f') }}}] = 1; + __scanString.whiteSpace[{{{ charCode('\r') }}}] = 1; __scanString.whiteSpace[' '] = 1; __scanString.whiteSpace['\t'] = 1; __scanString.whiteSpace['\n'] = 1; + __scanString.whiteSpace['\v'] = 1; + __scanString.whiteSpace['\f'] = 1; + __scanString.whiteSpace['\r'] = 1; } // Supports %x, %4x, %d.%d, %lld, %s, %f, %lf. // TODO: Support all format specifiers. diff --git a/src/modules.js b/src/modules.js index 9cbe88aa..6b3c5ffb 100644 --- a/src/modules.js +++ b/src/modules.js @@ -259,7 +259,7 @@ var Functions = { } if (phase != 'post' && singlePhase) { if (!doNotCreate) this.indexedFunctions[ident] = 0; // tell python we need this indexized - return "'{{ FI_" + ident + " }}'"; // something python will replace later + return "'{{ FI_" + toNiceIdent(ident) + " }}'"; // something python will replace later } else { var ret = this.indexedFunctions[ident]; if (!ret) { @@ -318,6 +318,7 @@ var Functions = { if (ASM_JS) { var curr = table[i]; if (curr && curr != '0' && !Functions.implementedFunctions[curr]) { + curr = toNiceIdent(curr); // fix Math.* to Math_* // This is a library function, we can't just put it in the function table, need a wrapper if (!wrapped[curr]) { var args = '', arg_coercions = '', call = curr + '(', retPre = '', retPost = ''; diff --git a/src/settings.js b/src/settings.js index ba1f6a83..d029598a 100644 --- a/src/settings.js +++ b/src/settings.js @@ -17,8 +17,8 @@ var QUANTUM_SIZE = 4; // This is the size of an individual field in a structure. // // Changing this from the default of 4 is deprecated. -var TARGET_X86 = 1; // For le32-unknown-nacl -var TARGET_LE32 = 0; // For i386-pc-linux-gnu +var TARGET_X86 = 0; // For i386-pc-linux-gnu +var TARGET_LE32 = 1; // For le32-unknown-nacl var CORRECT_SIGNS = 1; // Whether we make sure to convert unsigned values to signed values. // Decreases performance with additional runtime checks. Might not be |