diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/file_packager.py | 107 | ||||
-rw-r--r-- | tools/js-optimizer.js | 23 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-outline1-output.js | 136 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-outline1.js | 48 |
4 files changed, 256 insertions, 58 deletions
diff --git a/tools/file_packager.py b/tools/file_packager.py index 33ccebad..bb62e905 100644 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -329,13 +329,55 @@ if has_preloaded: # Data requests - for getting a block of data out of the big archive - have a similar API to XHRs code += ''' - function DataRequest() {} + function DataRequest(start, end, crunched, audio) { + this.start = start; + this.end = end; + this.crunched = crunched; + this.audio = audio; + } DataRequest.prototype = { requests: {}, open: function(mode, name) { + this.name = name; this.requests[name] = this; + Module['addRunDependency']('fp ' + this.name); + }, + send: function() {}, + onload: function() { + var data = this.byteArray.subarray(this.start, this.end); + var size = this.end - this.start; + var ptr = Module['_malloc'](size); // XXX leaked if a preload plugin replaces with new data + Module['HEAPU8'].set(data, ptr); + var arrayBuffer = Module['HEAPU8'].subarray(ptr, ptr + size); + assert(arrayBuffer, 'Loading file ' + name + ' failed'); + var byteArray = !arrayBuffer.subarray ? new Uint8Array(arrayBuffer) : arrayBuffer; + + if (this.crunched) { + var ddsHeader = byteArray.subarray(0, 128); + var that = this; + requestDecrunch(this.name, byteArray.subarray(128), function(ddsData) { + byteArray = new Uint8Array(ddsHeader.length + ddsData.length); + byteArray.set(ddsHeader, 0); + byteArray.set(ddsData, 128); + that.finish(byteArray); + }); + } else { + this.finish(byteArray); + } + }, + finish: function(byteArray) { + var that = this; + Module['FS_createPreloadedFile'](PATH.dirname(this.name), PATH.basename(this.name), byteArray, true, true, function() { + Module['removeRunDependency']('fp ' + that.name); + }, function() { + if (that.audio) { + Module['removeRunDependency']('fp ' + that.name); // workaround for chromium bug 124926 (still no audio with this, but at least we don't hang) + } else { + Runtime.warn('Preloading file ' + that.name + ' failed'); + } + }); + this.requests[this.name] = null; }, - send: function() {} }; ''' @@ -364,66 +406,23 @@ for file_ in data_files: # Preload varname = 'filePreload%d' % counter counter += 1 - dds = crunch and filename.endswith(CRUNCH_INPUT_SUFFIX) - - prepare = '' - finish = "Module['removeRunDependency']('fp %s');\n" % filename - - if dds: - # decompress crunch format into dds - prepare = ''' - var ddsHeader = byteArray.subarray(0, %(dds_header_size)d); - requestDecrunch('%(filename)s', byteArray.subarray(%(dds_header_size)d), function(ddsData) { - byteArray = new Uint8Array(ddsHeader.length + ddsData.length); - byteArray.set(ddsHeader, 0); - byteArray.set(ddsData, %(dds_header_size)d); -''' % { 'filename': filename, 'dds_header_size': DDS_HEADER_SIZE } - - finish += ''' - }); -''' - - code += ''' - var %(varname)s = new %(request)s(); - %(varname)s.open('GET', '%(filename)s', true); - %(varname)s.responseType = 'arraybuffer'; - %(varname)s.onload = function() { - var arrayBuffer = %(varname)s.response; - assert(arrayBuffer, 'Loading file %(filename)s failed.'); - var byteArray = !arrayBuffer.subarray ? new Uint8Array(arrayBuffer) : arrayBuffer; - %(prepare)s - Module['FS_createPreloadedFile']('%(dirname)s', '%(basename)s', byteArray, true, true, function() { - %(finish)s - }%(fail)s); - }; - Module['addRunDependency']('fp %(filename)s'); - %(varname)s.send(null); + code += ''' new DataRequest(%(start)d, %(end)d, %(crunched)s, %(audio)s).open('GET', '%(filename)s'); ''' % { - 'request': 'DataRequest', # In the past we also supported XHRs here - 'varname': varname, - 'filename': filename, - 'dirname': dirname, - 'basename': basename, - 'prepare': prepare, - 'finish': finish, - 'fail': '' if filename[-4:] not in AUDIO_SUFFIXES else ''', function() { Module['removeRunDependency']('fp %s') }''' % filename # workaround for chromium bug 124926 (still no audio with this, but at least we don't hang) - } + 'filename': file_['dstpath'], + 'start': file_['data_start'], + 'end': file_['data_end'], + 'crunched': '1' if crunch and filename.endswith(CRUNCH_INPUT_SUFFIX) else '0', + 'audio': '1' if filename[-4:] in AUDIO_SUFFIXES else '0', + } else: assert 0 if has_preloaded: # Get the big archive and split it up - use_data = '' + use_data = ' DataRequest.prototype.byteArray = byteArray;\n' for file_ in data_files: if file_['mode'] == 'preload': - use_data += ''' - curr = DataRequest.prototype.requests['%s']; - var data = byteArray.subarray(%d, %d); - var ptr = Module['_malloc'](%d); - Module['HEAPU8'].set(data, ptr); - curr.response = Module['HEAPU8'].subarray(ptr, ptr + %d); - curr.onload(); - ''' % (file_['dstpath'], file_['data_start'], file_['data_end'], file_['data_end'] - file_['data_start'], file_['data_end'] - file_['data_start']) + use_data += ' DataRequest.prototype.requests["%s"].onload();\n' % (file_['dstpath']) use_data += " Module['removeRunDependency']('datafile_%s');\n" % data_target if Compression.on: diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index a673e019..9a5104bf 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1236,7 +1236,7 @@ function vacuum(ast) { } } break; case 'label': { - if (node[2][0] === 'toplevel' && (!node[2][1] || node[2][1].length === 0)) { + if (node[2] && node[2][0] === 'toplevel' && (!node[2][1] || node[2][1].length === 0)) { return emptyNode(); } } break; @@ -3057,16 +3057,24 @@ function outline(ast) { var chunks = []; var currSize = 0; var currChunk = []; + var force = false; // when we hit a case X: that falls through, we force inclusion of everything until a full case parts.forEach(function(part) { var size = (part.condition ? measureSize(part.condition) : 0) + measureSize(part.body) + 5; // add constant for overhead of extra code assert(size > 0); - if (size + currSize >= minSize && currSize) { + if (size + currSize >= minSize && currSize && !force) { chunks.push(currChunk); currChunk = []; currSize = 0; } currChunk.push(part); currSize += size; + if (!isIf) { + var last = part.body; + last = last[stats.length-1]; + if (last && last[0] === 'block') last = last[1][last[1].length-1]; + if (last && last[0] === 'stat') last = last[1]; + force = !last || last[0] !== 'break'; + } }); assert(currSize); chunks.push(currChunk); @@ -3115,6 +3123,8 @@ function outline(ast) { }); } + var maxTotalOutlinings = Infinity; // debugging tool + // Prepares information for spilling of local variables function analyzeFunction(func, asmData) { var stack = []; // list of variables, each gets 8 bytes @@ -3134,7 +3144,7 @@ function outline(ast) { // The control variables are zeroed out when calling an outlined function, and after using // the value after they return. var size = measureSize(func); - asmData.maxOutlinings = Math.round(3*size/extraInfo.sizeToOutline); + asmData.maxOutlinings = Math.min(Math.round(3*size/extraInfo.sizeToOutline), maxTotalOutlinings); asmData.intendedPieces = Math.ceil(size/extraInfo.sizeToOutline); asmData.totalStackSize = stackSize + (stack.length + 2*asmData.maxOutlinings)*8; asmData.controlStackPos = function(i) { return stackSize + (stack.length + i)*8 }; @@ -3464,6 +3474,7 @@ function outline(ast) { asmData.splitCounter--; return []; } + maxTotalOutlinings--; for (var v in owned) { if (v != 'sp') delete asmData.vars[v]; // parent does not need these anymore } @@ -3620,6 +3631,8 @@ function outline(ast) { var funcs = ast[1]; + var maxTotalFunctions = Infinity; // debugging tool + var more = true; while (more) { more = false; @@ -3627,9 +3640,11 @@ function outline(ast) { var newFuncs = []; funcs.forEach(function(func) { + vacuum(func); // clear out empty nodes that affect code size var asmData = normalizeAsm(func); var size = measureSize(func); - if (size >= extraInfo.sizeToOutline) { + if (size >= extraInfo.sizeToOutline && maxTotalFunctions > 0) { + maxTotalFunctions--; aggressiveVariableElimination(func, asmData); flatten(func, asmData); analyzeFunction(func, asmData); diff --git a/tools/test-js-optimizer-asm-outline1-output.js b/tools/test-js-optimizer-asm-outline1-output.js index d8ea9446..895004d8 100644 --- a/tools/test-js-optimizer-asm-outline1-output.js +++ b/tools/test-js-optimizer-asm-outline1-output.js @@ -321,6 +321,48 @@ function chain() { helper$0 = HEAP32[sp + 8 >> 2] | 0; STACKTOP = sp; } +function switchh() { + var helper$0 = 0, helper$1 = 0, sp = 0; + sp = STACKTOP; + STACKTOP = STACKTOP + 296 | 0; + helper$0 = 1; + helper$1 = x; + if (helper$0) { + helper$0 = 0; + switch (helper$1 | 0) { + case 0: + { + f(0); + g(); + break; + } + default: + { + helper$0 = 1; + } + } + } + HEAP32[sp + 8 >> 2] = helper$0; + HEAP32[sp + 16 >> 2] = helper$1; + HEAP32[sp + 40 >> 2] = 0; + HEAP32[sp + 44 >> 2] = 0; + switchh$2(sp); + helper$0 = HEAP32[sp + 8 >> 2] | 0; + HEAP32[sp + 8 >> 2] = helper$0; + HEAP32[sp + 16 >> 2] = helper$1; + HEAP32[sp + 32 >> 2] = 0; + HEAP32[sp + 36 >> 2] = 0; + switchh$1(sp); + helper$0 = HEAP32[sp + 8 >> 2] | 0; + if (helper$0) { + helper$0 = 0; + HEAP32[sp + 16 >> 2] = helper$1; + HEAP32[sp + 24 >> 2] = 0; + HEAP32[sp + 28 >> 2] = 0; + switchh$0(sp); + } + STACKTOP = sp; +} function lin$0(sp) { sp = sp | 0; c(14); @@ -645,4 +687,98 @@ function chain$4(sp) { } HEAP32[sp + 8 >> 2] = helper$0; } +function switchh$0(sp) { + sp = sp | 0; + var helper$1 = 0; + helper$1 = HEAP32[sp + 16 >> 2] | 0; + switch (helper$1 | 0) { + case 4: + { + f(4); + g(); + } + case 5: + { + f(5); + g(); + } + case 6: + { + f(6); + g(); + } + default: + { + print(9); + } + } +} +function switchh$1(sp) { + sp = sp | 0; + var helper$0 = 0, helper$1 = 0; + helper$0 = HEAP32[sp + 8 >> 2] | 0; + helper$1 = HEAP32[sp + 16 >> 2] | 0; + if (helper$0) { + helper$0 = 0; + switch (helper$1 | 0) { + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 3: + { + f(3); + g(); + break; + } + default: + { + helper$0 = 1; + } + } + } + HEAP32[sp + 8 >> 2] = helper$0; +} +function switchh$2(sp) { + sp = sp | 0; + var helper$0 = 0, helper$1 = 0; + helper$0 = HEAP32[sp + 8 >> 2] | 0; + helper$1 = HEAP32[sp + 16 >> 2] | 0; + if (helper$0) { + helper$0 = 0; + switch (helper$1 | 0) { + case 1: + { + f(1); + g(); + break; + } + default: + { + helper$0 = 1; + } + } + } + if (helper$0) { + helper$0 = 0; + switch (helper$1 | 0) { + case 2: + { + f(2); + g(); + break; + } + default: + { + helper$0 = 1; + } + } + } + HEAP32[sp + 8 >> 2] = helper$0; +} diff --git a/tools/test-js-optimizer-asm-outline1.js b/tools/test-js-optimizer-asm-outline1.js index 311cb206..3c454182 100644 --- a/tools/test-js-optimizer-asm-outline1.js +++ b/tools/test-js-optimizer-asm-outline1.js @@ -259,5 +259,53 @@ function chain() { print(99); } } +function switchh() { + switch (x) { + case 0: { + f(0); + g(); + break; + } + case 1: { + f(1); + g(); + break; + } + case 2: { + f(2); + g(); + break; + } + case 21: // gotta keem em unseparated + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 3: { // these too + f(3); + g(); + break; + } + case 4: { + f(4); + g(); + } + case 5: { + f(5); + g(); + } + case 6: { + f(6); + g(); + } + default: { + print(9); + } + } +} // EMSCRIPTEN_GENERATED_FUNCTIONS // EXTRA_INFO: { "sizeToOutline": 30, "allowCostlyOutlines": 1 } |