diff options
-rwxr-xr-x | emcc | 3 | ||||
-rw-r--r-- | src/library_browser.js | 9 | ||||
-rw-r--r-- | src/library_gl.js | 227 | ||||
-rw-r--r-- | src/parseTools.js | 4 | ||||
-rw-r--r-- | src/relooper/Relooper.cpp | 27 | ||||
-rw-r--r-- | src/relooper/Relooper.h | 4 | ||||
-rw-r--r-- | src/relooper/test.txt | 4 | ||||
-rw-r--r-- | system/lib/libc/musl/src/math/__cos.c | 71 | ||||
-rw-r--r-- | system/lib/libc/musl/src/math/__sin.c | 64 | ||||
-rw-r--r-- | system/lib/libc/musl/src/stdio/fputwc.c | 21 | ||||
-rw-r--r-- | system/lib/libc/musl/src/stdio/fputws.c | 30 | ||||
-rw-r--r-- | system/lib/libc/musl/src/stdio/vswprintf.c | 17 | ||||
-rw-r--r-- | system/lib/libcextra.symbols | 2 | ||||
-rw-r--r-- | tests/core/test_wprintf.c | 50 | ||||
-rw-r--r-- | tests/core/test_wprintf.out | 35 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test-output.js | 506 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test.js | 651 | ||||
-rw-r--r-- | tools/js-optimizer.js | 17 | ||||
-rw-r--r-- | tools/shared.py | 2 |
19 files changed, 1654 insertions, 90 deletions
@@ -1536,7 +1536,9 @@ try: 'wctype_l.c', ]], ['math', [ + '__cos.c', '__cosdf.c', + '__sin.c', '__sindf.c', 'ilogb.c', 'ilogbf.c', @@ -1593,6 +1595,7 @@ try: 'vwprintf.c', 'wprintf.c', 'fputwc.c', + 'fputws.c', ]], ['stdlib', [ 'ecvt.c', diff --git a/src/library_browser.js b/src/library_browser.js index d5e35339..458a8dd2 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -775,6 +775,15 @@ mergeInto(LibraryManager.library, { return; } + // Signal GL rendering layer that processing of a new frame is about to start. This helps it optimize + // VBO double-buffering and reduce GPU stalls. +#if FULL_ES2 + GL.newRenderingFrameStarted(); +#endif +#if LEGACY_GL_EMULATION + GL.newRenderingFrameStarted(); +#endif + if (Module['preMainLoop']) { Module['preMainLoop'](); } diff --git a/src/library_gl.js b/src/library_gl.js index f6978c04..61ca8957 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -57,6 +57,7 @@ var LibraryGL = { unpackAlignment: 4, // default alignment is 4 bytes init: function() { + GL.createLog2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE); Browser.moduleContextCreatedCallbacks.push(GL.initExtensions); }, @@ -81,36 +82,58 @@ var LibraryGL = { miniTempBuffer: null, miniTempBufferViews: [0], // index i has the view of size i+1 - // Large temporary buffers + // When user GL code wants to render from client-side memory, we need to upload the vertex data to a temp VBO + // for rendering. Maintain a set of temp VBOs that are created-on-demand to appropriate sizes, and never destroyed. + // Also, for best performance the VBOs are double-buffered, i.e. every second frame we switch the set of VBOs we + // upload to, so that rendering from the previous frame is not disturbed by uploading from new data to it, which + // could cause a GPU-CPU pipeline stall. + // Note that index buffers are not double-buffered (at the moment) in this manner. MAX_TEMP_BUFFER_SIZE: {{{ GL_MAX_TEMP_BUFFER_SIZE }}}, - tempBufferIndexLookup: null, - tempVertexBuffers: null, - tempIndexBuffers: null, + tempVertexBuffers1: [], + tempVertexBufferCounters1: [], + tempVertexBuffers2: [], + tempVertexBufferCounters2: [], + // Maximum number of temp VBOs of one size to maintain, after that we start reusing old ones, which is safe but can give + // a performance impact. If CPU-GPU stalls are a problem, increasing this might help. + numTempVertexBuffersPerSize: 64, // (const) + tempIndexBuffers: [], tempQuadIndexBuffer: null, - generateTempBuffers: function(quads) { - GL.tempBufferIndexLookup = new Uint8Array(GL.MAX_TEMP_BUFFER_SIZE+1); - GL.tempVertexBuffers = []; - GL.tempIndexBuffers = []; - var last = -1, curr = -1; - var size = 1; - for (var i = 0; i <= GL.MAX_TEMP_BUFFER_SIZE; i++) { - if (i > size) { - size <<= 1; + // Precompute a lookup table for the function ceil(log2(x)), i.e. how many bits are needed to represent x, or, + // if x was rounded up to next pow2, which index is the single '1' bit at? + // Then log2ceilLookup[x] returns ceil(log2(x)). + log2ceilLookup: null, + createLog2ceilLookup: function(maxValue) { + GL.log2ceilLookup = new Uint8Array(maxValue+1); + var log2 = 0; + var pow2 = 1; + GL.log2ceilLookup[0] = 0; + for(var i = 1; i <= maxValue; ++i) { + if (i > pow2) { + pow2 <<= 1; + ++log2; } - if (size != last) { - curr++; - GL.tempVertexBuffers[curr] = GLctx.createBuffer(); - GLctx.bindBuffer(GLctx.ARRAY_BUFFER, GL.tempVertexBuffers[curr]); - GLctx.bufferData(GLctx.ARRAY_BUFFER, size, GLctx.DYNAMIC_DRAW); - GLctx.bindBuffer(GLctx.ARRAY_BUFFER, null); - GL.tempIndexBuffers[curr] = GLctx.createBuffer(); - GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.tempIndexBuffers[curr]); - GLctx.bufferData(GLctx.ELEMENT_ARRAY_BUFFER, size, GLctx.DYNAMIC_DRAW); - GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, null); - last = size; + GL.log2ceilLookup[i] = log2; + } + }, + + generateTempBuffers: function(quads) { + var largestIndex = GL.log2ceilLookup[GL.MAX_TEMP_BUFFER_SIZE]; + GL.tempVertexBufferCounters1.length = GL.tempVertexBufferCounters2.length = largestIndex+1; + GL.tempVertexBuffers1.length = GL.tempVertexBuffers2.length = largestIndex+1; + GL.tempIndexBuffers.length = largestIndex+1; + for(var i = 0; i <= largestIndex; ++i) { + GL.tempIndexBuffers[i] = null; // Created on-demand + GL.tempVertexBufferCounters1[i] = GL.tempVertexBufferCounters2[i] = 0; + var ringbufferLength = GL.numTempVertexBuffersPerSize; + GL.tempVertexBuffers1[i] = []; + GL.tempVertexBuffers2[i] = []; + var ringbuffer1 = GL.tempVertexBuffers1[i]; + var ringbuffer2 = GL.tempVertexBuffers2[i]; + ringbuffer1.length = ringbuffer2.length = ringbufferLength; + for(var j = 0; j < ringbufferLength; ++j) { + ringbuffer1[j] = ringbuffer2[j] = null; // Created on-demand } - GL.tempBufferIndexLookup[i] = curr; } if (quads) { @@ -140,6 +163,53 @@ var LibraryGL = { } }, + getTempVertexBuffer: function getTempVertexBuffer(sizeBytes) { + var idx = GL.log2ceilLookup[sizeBytes]; + var ringbuffer = GL.tempVertexBuffers1[idx]; + var nextFreeBufferIndex = GL.tempVertexBufferCounters1[idx]; + GL.tempVertexBufferCounters1[idx] = (GL.tempVertexBufferCounters1[idx]+1) & (GL.numTempVertexBuffersPerSize-1); + var vbo = ringbuffer[nextFreeBufferIndex]; + if (vbo) { + return vbo; + } + var prevVBO = GLctx.getParameter(GLctx.ARRAY_BUFFER_BINDING); + ringbuffer[nextFreeBufferIndex] = GLctx.createBuffer(); + GLctx.bindBuffer(GLctx.ARRAY_BUFFER, ringbuffer[nextFreeBufferIndex]); + GLctx.bufferData(GLctx.ARRAY_BUFFER, 1 << idx, GLctx.DYNAMIC_DRAW); + GLctx.bindBuffer(GLctx.ARRAY_BUFFER, prevVBO); + return ringbuffer[nextFreeBufferIndex]; + }, + + getTempIndexBuffer: function getTempIndexBuffer(sizeBytes) { + var idx = GL.log2ceilLookup[sizeBytes]; + var ibo = GL.tempIndexBuffers[idx]; + if (ibo) { + return ibo; + } + var prevIBO = GLctx.getParameter(GLctx.ELEMENT_ARRAY_BUFFER_BINDING); + GL.tempIndexBuffers[idx] = GLctx.createBuffer(); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.tempIndexBuffers[idx]); + GLctx.bufferData(GLctx.ELEMENT_ARRAY_BUFFER, 1 << idx, GLctx.DYNAMIC_DRAW); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, prevIBO); + return GL.tempIndexBuffers[idx]; + }, + + // Called at start of each new WebGL rendering frame. This swaps the doublebuffered temp VB memory pointers, + // so that every second frame utilizes different set of temp buffers. The aim is to keep the set of buffers + // being rendered, and the set of buffers being updated disjoint. + newRenderingFrameStarted: function newRenderingFrameStarted() { + var vb = GL.tempVertexBuffers1; + GL.tempVertexBuffers1 = GL.tempVertexBuffers2; + GL.tempVertexBuffers2 = vb; + vb = GL.tempVertexBufferCounters1; + GL.tempVertexBufferCounters1 = GL.tempVertexBufferCounters2; + GL.tempVertexBufferCounters2 = vb; + var largestIndex = GL.log2ceilLookup[GL.MAX_TEMP_BUFFER_SIZE]; + for(var i = 0; i <= largestIndex; ++i) { + GL.tempVertexBufferCounters1[i] = 0; + } + }, + // Find a token in a shader source string findToken: function(source, token) { function isIdentChar(ch) { @@ -446,9 +516,6 @@ var LibraryGL = { preDrawHandleClientVertexAttribBindings: function preDrawHandleClientVertexAttribBindings(count) { GL.resetBufferBinding = false; - var used = GL.usedTempBuffers; - used.length = 0; - // TODO: initial pass to detect ranges we need to upload, might not need an upload per attrib for (var i = 0; i < GL.maxVertexAttribs; ++i) { var cb = GL.clientBuffers[i]; @@ -457,15 +524,7 @@ var LibraryGL = { GL.resetBufferBinding = true; var size = GL.calcBufLength(cb.size, cb.type, cb.stride, count); - var index = GL.tempBufferIndexLookup[size]; - var buf; - do { -#if ASSERTIONS - assert(index < GL.tempVertexBuffers.length); -#endif - buf = GL.tempVertexBuffers[index++]; - } while (used.indexOf(buf) >= 0); - used.push(buf); + var buf = GL.getTempVertexBuffer(size); GLctx.bindBuffer(GLctx.ARRAY_BUFFER, buf); GLctx.bufferSubData(GLctx.ARRAY_BUFFER, 0, @@ -2742,14 +2801,6 @@ var LibraryGL = { this.key0 = -1; // The key of this texture unit must be recomputed when rendering the next time. GLImmediate.currentRenderer = null; // The currently used renderer must be re-evaluated at next render. } - this.traverseState = function(keyView) { - if (this.key0 == -1) { - this.recomputeKey(); - } - keyView.next(this.key0); - keyView.next(this.key1); - keyView.next(this.key2); - }; } function CTexUnit() { @@ -2758,26 +2809,55 @@ var LibraryGL = { this.enabled_tex2D = false; this.enabled_tex3D = false; this.enabled_texCube = false; + this.texTypesEnabled = 0; // A bitfield combination of the four flags above, used for fast access to operations. this.traverseState = function CTexUnit_traverseState(keyView) { - var texUnitType = this.getTexType(); - keyView.next(texUnitType); - if (!texUnitType) return; - this.env.traverseState(keyView); + if (this.texTypesEnabled) { + if (this.env.key0 == -1) { + this.env.recomputeKey(); + } + keyView.next(this.texTypesEnabled | (this.env.key0 << 4)); + keyView.next(this.env.key1); + keyView.next(this.env.key2); + } else { + // For correctness, must traverse a zero value, theoretically a subsequent integer key could collide with this value otherwise. + keyView.next(0); + } }; }; // Class impls: CTexUnit.prototype.enabled = function CTexUnit_enabled() { - return this.getTexType() != 0; + return this.texTypesEnabled; } CTexUnit.prototype.genPassLines = function CTexUnit_genPassLines(passOutputVar, passInputVar, texUnitID) { if (!this.enabled()) { return ["vec4 " + passOutputVar + " = " + passInputVar + ";"]; } - - return this.env.genPassLines(passOutputVar, passInputVar, texUnitID); + var lines = this.env.genPassLines(passOutputVar, passInputVar, texUnitID).join('\n'); + + var texLoadLines = ''; + var texLoadRegex = /(texture.*?\(.*?\))/g; + var loadCounter = 0; + var load; + + // As an optimization, merge duplicate identical texture loads to one var. + while(load = texLoadRegex.exec(lines)) { + var texLoadExpr = load[1]; + var secondOccurrence = lines.slice(load.index+1).indexOf(texLoadExpr); + if (secondOccurrence != -1) { // And also has a second occurrence of same load expression.. + // Create new var to store the common load. + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var texLoadVar = prefix + 'texload' + loadCounter++; + var texLoadLine = 'vec4 ' + texLoadVar + ' = ' + texLoadExpr + ';\n'; + texLoadLines += texLoadLine + '\n'; // Store the generated texture load statements in a temp string to not confuse regex search in progress. + lines = lines.split(texLoadExpr).join(texLoadVar); + // Reset regex search, since we modified the string. + texLoadRegex = /(texture.*\(.*\))/g; + } + } + return [texLoadLines + lines]; } CTexUnit.prototype.getTexType = function CTexUnit_getTexType() { @@ -2898,13 +2978,18 @@ var LibraryGL = { var alphaLines = this.genCombinerLines(false, alphaVar, passInputVar, texUnitID, this.alphaCombiner, this.alphaSrc, this.alphaOp); + + // Generate scale, but avoid generating an identity op that multiplies by one. + var scaledColor = (this.colorScale == 1) ? colorVar : (colorVar + " * " + valToFloatLiteral(this.colorScale)); + var scaledAlpha = (this.alphaScale == 1) ? alphaVar : (alphaVar + " * " + valToFloatLiteral(this.alphaScale)); + var line = [ "vec4 " + passOutputVar, " = ", "vec4(", - colorVar + " * " + valToFloatLiteral(this.colorScale), + scaledColor, ", ", - alphaVar + " * " + valToFloatLiteral(this.alphaScale), + scaledAlpha, ")", ";", ].join(""); @@ -3084,12 +3169,7 @@ var LibraryGL = { traverseState: function(keyView) { for (var i = 0; i < s_texUnits.length; i++) { - var texUnit = s_texUnits[i]; - var enabled = texUnit.enabled(); - keyView.next(enabled); - if (enabled) { - texUnit.traverseState(keyView); - } + s_texUnits[i].traverseState(keyView); } }, @@ -3113,24 +3193,28 @@ var LibraryGL = { if (!cur.enabled_tex1D) { GLImmediate.currentRenderer = null; // Renderer state changed, and must be recreated or looked up again. cur.enabled_tex1D = true; + cur.texTypesEnabled |= 1; } break; case GL_TEXTURE_2D: if (!cur.enabled_tex2D) { GLImmediate.currentRenderer = null; cur.enabled_tex2D = true; + cur.texTypesEnabled |= 2; } break; case GL_TEXTURE_3D: if (!cur.enabled_tex3D) { GLImmediate.currentRenderer = null; cur.enabled_tex3D = true; + cur.texTypesEnabled |= 4; } break; case GL_TEXTURE_CUBE_MAP: if (!cur.enabled_texCube) { GLImmediate.currentRenderer = null; cur.enabled_texCube = true; + cur.texTypesEnabled |= 8; } break; } @@ -3143,24 +3227,28 @@ var LibraryGL = { if (cur.enabled_tex1D) { GLImmediate.currentRenderer = null; // Renderer state changed, and must be recreated or looked up again. cur.enabled_tex1D = false; + cur.texTypesEnabled &= ~1; } break; case GL_TEXTURE_2D: if (cur.enabled_tex2D) { GLImmediate.currentRenderer = null; cur.enabled_tex2D = false; + cur.texTypesEnabled &= ~2; } break; case GL_TEXTURE_3D: if (cur.enabled_tex3D) { GLImmediate.currentRenderer = null; cur.enabled_tex3D = false; + cur.texTypesEnabled &= ~4; } break; case GL_TEXTURE_CUBE_MAP: if (cur.enabled_texCube) { GLImmediate.currentRenderer = null; cur.enabled_texCube = false; + cur.texTypesEnabled &= ~8; } break; } @@ -3434,7 +3522,6 @@ var LibraryGL = { // we maintain a cache of renderers, optimized to not generate garbage var attributes = GLImmediate.liveClientAttributes; var cacheMap = GLImmediate.rendererCache; - var temp; var keyView = cacheMap.getStaticKeyView().reset(); // By attrib state: @@ -3442,7 +3529,6 @@ var LibraryGL = { for (var i = 0; i < attributes.length; i++) { enabledAttributesKey |= 1 << attributes[i].name; } - keyView.next(enabledAttributesKey); // By fog state: var fogParam = 0; @@ -3459,13 +3545,17 @@ var LibraryGL = { break; } } - keyView.next(fogParam); + keyView.next((enabledAttributesKey << 2) | fogParam); +#if !GL_FFP_ONLY // By cur program: keyView.next(GL.currProgram); if (!GL.currProgram) { +#endif GLImmediate.TexEnvJIT.traverseState(keyView); +#if !GL_FFP_ONLY } +#endif // If we don't already have it, create it. var renderer = keyView.get(); @@ -3720,7 +3810,7 @@ var LibraryGL = { #if ASSERTIONS assert(end <= GL.MAX_TEMP_BUFFER_SIZE, 'too much vertex data'); #endif - arrayBuffer = GL.tempVertexBuffers[GL.tempBufferIndexLookup[end]]; + arrayBuffer = GL.getTempVertexBuffer(end); // TODO: consider using the last buffer we bound, if it was larger. downside is larger buffer, but we might avoid rebinding and preparing } else { arrayBuffer = GL.currArrayBuffer; @@ -4028,11 +4118,12 @@ var LibraryGL = { if (!Module.useWebGL) return; // a 2D canvas may be currently used TODO: make sure we are actually called in that case - GLImmediate.TexEnvJIT.init(GLctx); - // User can override the maximum number of texture units that we emulate. Using fewer texture units increases runtime performance // slightly, so it is advantageous to choose as small value as needed. GLImmediate.MAX_TEXTURES = Module['GL_MAX_TEXTURE_IMAGE_UNITS'] || GLctx.getParameter(GLctx.MAX_TEXTURE_IMAGE_UNITS); + + GLImmediate.TexEnvJIT.init(GLctx, GLImmediate.MAX_TEXTURES); + GLImmediate.NUM_ATTRIBUTES = 3 /*pos+normal+color attributes*/ + GLImmediate.MAX_TEXTURES; GLImmediate.clientAttributes = []; GLEmulation.enabledClientAttribIndices = []; @@ -4221,7 +4312,7 @@ var LibraryGL = { #if ASSERTIONS assert(numProvidedIndexes << 1 <= GL.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (a)'); #endif - var indexBuffer = GL.tempIndexBuffers[GL.tempBufferIndexLookup[numProvidedIndexes << 1]]; + var indexBuffer = GL.getTempIndexBuffer(numProvidedIndexes << 1); GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, indexBuffer); GLctx.bufferSubData(GLctx.ELEMENT_ARRAY_BUFFER, 0, {{{ makeHEAPView('U16', 'ptr', 'ptr + (numProvidedIndexes << 1)') }}}); ptr = 0; @@ -4986,7 +5077,7 @@ var LibraryGL = { var buf; if (!GL.currElementArrayBuffer) { var size = GL.calcBufLength(1, type, 0, count); - buf = GL.tempIndexBuffers[GL.tempBufferIndexLookup[size]]; + buf = GL.getTempIndexBuffer(size); GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, buf); GLctx.bufferSubData(GLctx.ELEMENT_ARRAY_BUFFER, 0, diff --git a/src/parseTools.js b/src/parseTools.js index b7f97a40..be0cbcab 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -2150,9 +2150,9 @@ function makeRounding(value, bits, signed, floatConversion) { } } // Math.floor is reasonably fast if we don't care about corrections (and even correct if unsigned) - if (!correctRoundings() || !signed) return 'Math_floor(' + value + ')'; + if (!correctRoundings() || !signed) return '(+Math_floor(' + value + '))'; // We are left with >32 bits - return makeInlineCalculation(makeComparison('VALUE', '>=', '0', 'float') + ' ? Math_floor(VALUE) : Math_ceil(VALUE)', value, 'tempBigIntR'); + return makeInlineCalculation(makeComparison('VALUE', '>=', '0', 'float') + ' ? +Math_floor(VALUE) : +Math_ceil(VALUE)', value, 'tempBigIntR'); } } diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp index d5772c62..204986da 100644 --- a/src/relooper/Relooper.cpp +++ b/src/relooper/Relooper.cpp @@ -322,12 +322,26 @@ void MultipleShape::RenderLoopPostfix() { void MultipleShape::Render(bool InLoop) { RenderLoopPrefix(); - bool First = true; + + // We know that blocks with the same Id were split from the same source, so their contents are identical and they are logically the same, so re-merge them here + typedef std::map<int, Shape*> IdShapeMap; + IdShapeMap IdMap; for (BlockShapeMap::iterator iter = InnerMap.begin(); iter != InnerMap.end(); iter++) { + int Id = iter->first->Id; + IdShapeMap::iterator Test = IdMap.find(Id); + if (Test != IdMap.end()) { + assert(Shape::IsSimple(iter->second) && Shape::IsSimple(Test->second)); // we can only merge simple blocks, something horrible has gone wrong if we see anything else + continue; + } + IdMap[iter->first->Id] = iter->second; + } + + bool First = true; + for (IdShapeMap::iterator iter = IdMap.begin(); iter != IdMap.end(); iter++) { if (AsmJS) { - PrintIndented("%sif ((label|0) == %d) {\n", First ? "" : "else ", iter->first->Id); + PrintIndented("%sif ((label|0) == %d) {\n", First ? "" : "else ", iter->first); } else { - PrintIndented("%sif (label == %d) {\n", First ? "" : "else ", iter->first->Id); + PrintIndented("%sif (label == %d) {\n", First ? "" : "else ", iter->first); } First = false; Indenter::Indent(); @@ -391,8 +405,8 @@ Relooper::~Relooper() { for (unsigned i = 0; i < Shapes.size(); i++) delete Shapes[i]; } -void Relooper::AddBlock(Block *New) { - New->Id = BlockIdCounter++; +void Relooper::AddBlock(Block *New, int Id) { + New->Id = Id == -1 ? BlockIdCounter++ : Id; Blocks.push_back(New); } @@ -446,8 +460,7 @@ void Relooper::Calculate(Block *Entry) { for (BlockSet::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) { Block *Prior = *iter; Block *Split = new Block(Original->Code, Original->BranchVar); - Parent->AddBlock(Split); - PrintDebug(" to %d\n", Split->Id); + Parent->AddBlock(Split, Original->Id); Split->BranchesIn.insert(Prior); Branch *Details = Prior->BranchesOut[Original]; Prior->BranchesOut[Split] = new Branch(Details->Condition, Details->Code); diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h index 6b9394db..85adf359 100644 --- a/src/relooper/Relooper.h +++ b/src/relooper/Relooper.h @@ -57,7 +57,7 @@ struct Block { BlockBranchMap ProcessedBranchesOut; BlockSet ProcessedBranchesIn; Shape *Parent; // The shape we are directly inside - int Id; // A unique identifier, defined when added to relooper + int Id; // A unique identifier, defined when added to relooper. Note that this uniquely identifies a *logical* block - if we split it, the two instances have the same content *and* the same Id const char *Code; // The string representation of the code in this block. Owning pointer (we copy the input) const char *BranchVar; // If we have more than one branch out, the variable whose value determines where we go bool IsCheckedMultipleEntry; // If true, we are a multiple entry, so reaching us requires setting the label variable @@ -191,7 +191,7 @@ struct Relooper { Relooper(); ~Relooper(); - void AddBlock(Block *New); + void AddBlock(Block *New, int Id=-1); // Calculates the shapes void Calculate(Block *Entry); diff --git a/src/relooper/test.txt b/src/relooper/test.txt index cb02b867..82b02ad7 100644 --- a/src/relooper/test.txt +++ b/src/relooper/test.txt @@ -91,7 +91,7 @@ } default: { var $x_1 = $x_0; - label = 8; + label = 7; break L1; } } @@ -106,7 +106,7 @@ } } } - if (label == 8) { + if (label == 7) { // code 7 } // code 4 diff --git a/system/lib/libc/musl/src/math/__cos.c b/system/lib/libc/musl/src/math/__cos.c new file mode 100644 index 00000000..46cefb38 --- /dev/null +++ b/system/lib/libc/musl/src/math/__cos.c @@ -0,0 +1,71 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_cos.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * __cos( x, y ) + * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * + * Algorithm + * 1. Since cos(-x) = cos(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. + * 3. cos(x) is approximated by a polynomial of degree 14 on + * [0,pi/4] + * 4 14 + * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x + * where the remez error is + * + * | 2 4 6 8 10 12 14 | -58 + * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 + * | | + * + * 4 6 8 10 12 14 + * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then + * cos(x) ~ 1 - x*x/2 + r + * since cos(x+y) ~ cos(x) - sin(x)*y + * ~ cos(x) - x*y, + * a correction term is necessary in cos(x) and hence + * cos(x+y) = 1 - (x*x/2 - (r - x*y)) + * For better accuracy, rearrange to + * cos(x+y) ~ w + (tmp + (r-x*y)) + * where w = 1 - x*x/2 and tmp is a tiny correction term + * (1 - x*x/2 == w + tmp exactly in infinite precision). + * The exactness of w + tmp in infinite precision depends on w + * and tmp having the same precision as x. If they have extra + * precision due to compiler bugs, then the extra precision is + * only good provided it is retained in all terms of the final + * expression for cos(). Retention happens in all cases tested + * under FreeBSD, so don't pessimize things by forcibly clipping + * any extra precision in w. + */ + +#include "libm.h" + +static const double +C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ +C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ +C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ +C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ +C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ +C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ + +double __cos(double x, double y) +{ + double_t hz,z,r,w; + + z = x*x; + w = z*z; + r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6)); + hz = 0.5*z; + w = 1.0-hz; + return w + (((1.0-w)-hz) + (z*r-x*y)); +} diff --git a/system/lib/libc/musl/src/math/__sin.c b/system/lib/libc/musl/src/math/__sin.c new file mode 100644 index 00000000..40309496 --- /dev/null +++ b/system/lib/libc/musl/src/math/__sin.c @@ -0,0 +1,64 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_sin.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* __sin( x, y, iy) + * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). + * + * Algorithm + * 1. Since sin(-x) = -sin(x), we need only to consider positive x. + * 2. Callers must return sin(-0) = -0 without calling here since our + * odd polynomial is not evaluated in a way that preserves -0. + * Callers may do the optimization sin(x) ~ x for tiny x. + * 3. sin(x) is approximated by a polynomial of degree 13 on + * [0,pi/4] + * 3 13 + * sin(x) ~ x + S1*x + ... + S6*x + * where + * + * |sin(x) 2 4 6 8 10 12 | -58 + * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 + * | x | + * + * 4. sin(x+y) = sin(x) + sin'(x')*y + * ~ sin(x) + (1-x*x/2)*y + * For better accuracy, let + * 3 2 2 2 2 + * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) + * then 3 2 + * sin(x) = x + (S1*x + (x *(r-y/2)+y)) + */ + +#include "libm.h" + +static const double +S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ +S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ +S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ +S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ +S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ +S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ + +double __sin(double x, double y, int iy) +{ + double_t z,r,v,w; + + z = x*x; + w = z*z; + r = S2 + z*(S3 + z*S4) + z*w*(S5 + z*S6); + v = z*x; + if (iy == 0) + return x + v*(S1 + z*r); + else + return x - ((z*(0.5*y - v*r) - y) - v*S1); +} diff --git a/system/lib/libc/musl/src/stdio/fputwc.c b/system/lib/libc/musl/src/stdio/fputwc.c index e87e47d4..603fa615 100644 --- a/system/lib/libc/musl/src/stdio/fputwc.c +++ b/system/lib/libc/musl/src/stdio/fputwc.c @@ -17,15 +17,28 @@ wint_t __fputwc_unlocked(wchar_t c, FILE *f) l = wctomb((void *)f->wpos, c); if (l < 0) c = WEOF; else f->wpos += l; -#else - if (isascii(c)) { - c = fputc(c, f); -#endif } else { l = wctomb(mbc, c); if (l < 0 || __fwritex((void *)mbc, l, f) < l) c = WEOF; } return c; +#else + if (isascii(c)) { + c = fputc(c, f); + } else { + l = wctomb(mbc, c); + if (l < 0) c = WEOF; + else { + for (int i = 0; i < l; i++) { + if (fputc(mbc[i], f) == EOF) { + c = WEOF; + break; + } + } + } + } +#endif + return c; } wint_t fputwc(wchar_t c, FILE *f) diff --git a/system/lib/libc/musl/src/stdio/fputws.c b/system/lib/libc/musl/src/stdio/fputws.c new file mode 100644 index 00000000..70e004c9 --- /dev/null +++ b/system/lib/libc/musl/src/stdio/fputws.c @@ -0,0 +1,30 @@ +#include "stdio_impl.h" +#include <wchar.h> + +int fputws(const wchar_t *restrict ws, FILE *restrict f) +{ + unsigned char buf[BUFSIZ]; + size_t l=0; + + FLOCK(f); + +#if 0 // XXX EMSCRIPTEN + f->mode |= f->mode+1; +#endif + + while (ws && (l = wcsrtombs((void *)buf, (void*)&ws, sizeof buf, 0))+1 > 1) +#if 0 // XXX EMSCRIPTEN + if (__fwritex(buf, l, f) < l) { +#else + if (fwrite(buf, 1, l, f) < l) { +#endif + FUNLOCK(f); + return -1; + } + + FUNLOCK(f); + + return l; /* 0 or -1 */ +} + +weak_alias(fputws, fputws_unlocked); diff --git a/system/lib/libc/musl/src/stdio/vswprintf.c b/system/lib/libc/musl/src/stdio/vswprintf.c index 7d237bae..e906f7ae 100644 --- a/system/lib/libc/musl/src/stdio/vswprintf.c +++ b/system/lib/libc/musl/src/stdio/vswprintf.c @@ -29,6 +29,7 @@ static size_t sw_write(FILE *f, const unsigned char *s, size_t l) int vswprintf(wchar_t *restrict s, size_t n, const wchar_t *restrict fmt, va_list ap) { +#if 0 // XXX EMSCRIPTEN int r; FILE f; unsigned char buf[256]; @@ -50,4 +51,20 @@ int vswprintf(wchar_t *restrict s, size_t n, const wchar_t *restrict fmt, va_lis r = vfwprintf(&f, fmt, ap); sw_write(&f, 0, 0); return r>=n ? -1 : r; +#else + // XXX EMSCRIPTEN: use memfs through libc fs + // we write to a file, which is in multibyte, then we read, then expand to widechar + #define TEMPFILE "emscripten.vswprintf.temp.buffer" + FILE *f = fopen(TEMPFILE, "wb"); + int r = vfwprintf(f, fmt, ap); + fclose(f); + f = fopen(TEMPFILE, "rb"); + char buffer[r+1]; + fread(buffer, 1, r, f); + fclose(f); + remove(TEMPFILE); + buffer[r] = 0; + r = mbstowcs(s, buffer, n); + return r>=n ? -1 : r; +#endif } diff --git a/system/lib/libcextra.symbols b/system/lib/libcextra.symbols index 00dd899d..6f1039f1 100644 --- a/system/lib/libcextra.symbols +++ b/system/lib/libcextra.symbols @@ -1,3 +1,4 @@ + T __cos T __cosdf T __fputwc_unlocked T __intscan @@ -9,6 +10,7 @@ C __optpos D __optreset W __posix_getopt + T __sin T __sindf T __strchrnul T __strxfrm_l diff --git a/tests/core/test_wprintf.c b/tests/core/test_wprintf.c index e938bf69..b5f8d6ab 100644 --- a/tests/core/test_wprintf.c +++ b/tests/core/test_wprintf.c @@ -1,7 +1,44 @@ +#include <stdio.h> +#include <string.h> +#include <stdarg.h> #include <wchar.h> -int main() +void PrintWide ( const wchar_t * format, ... ) { + wchar_t buffer[256]; + memset(buffer, 0, 256); + va_list args; + va_start ( args, format ); + wprintf(L"format starts with 0x%x\n", *(int*)format); + wprintf(L"fmt continues with 0x%x\n", *(((int*)format) + 1)); + wprintf(L"fmt continues with 0x%x\n", *(((int*)format) + 2)); + int r = vswprintf ( buffer, 256, format, args ); + wprintf(L"vswprintf told us %d\n", r); + wprintf(L"vswoutput st-rts with 0x%x\n", *(int*)buffer); + wprintf(L"vsw continues with 0x%x\n", *(((int*)buffer) + 1)); + wprintf(L"vsw continues with 0x%x\n", *(((int*)buffer) + 2)); + wprintf(buffer); + va_end ( args ); +} + +int main () +{ + FILE *f = fopen("test.dat", "wb"); + int num = fwprintf(f, L"hello %d", 5); + wprintf(L"fwprintf told us %d\n", num); + fclose(f); + f = fopen("test.dat", "rb"); + fseek(f, 0, SEEK_END); + int size = ftell(f); + fclose(f); + wprintf(L"file size is %d\n", size); + + wchar_t str[] = L"test string has %d wide characters.\n"; + wprintf(L"str starts with 0x%x\n", *(int*)str); + wprintf(L"str continues with 0x%x\n", *(((int*)str) + 1)); + wprintf(L"str continues with 0x%x\n", *(((int*)str) + 2)); + PrintWide ( str, wcslen(str) ); + wprintf (L"Characters: %lc %lc \n", L'a', 65); wprintf (L"Decimals: %d %ld\n", 1977, 650000L); wprintf (L"Preceding with blanks: %10d \n", 1977); @@ -10,6 +47,17 @@ int main() wprintf (L"floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416); wprintf (L"Width trick: %*d \n", 5, 10); wprintf (L"%ls \n", L"A wide string"); + + wchar_t buffer [100]; + memset(buffer, 0, sizeof(buffer)); + int cx; + cx = swprintf(buffer, 100, L"The half of %d is %d", 80, 80/2); + wprintf(L"swprintf told us %d\n", cx); + for (int i = 0; i < 10; i++) wprintf(L"pre %d\n", ((int*)buffer)[i]); + swprintf (buffer+cx, 100-cx-1, L", and the half of that is %d.\n", 80/2/2); + for (int i = 0; i < 10; i++) wprintf(L"post %d\n", ((int*)buffer)[i]); + wprintf(buffer); + return 0; } diff --git a/tests/core/test_wprintf.out b/tests/core/test_wprintf.out index f85abebb..e074743d 100644 --- a/tests/core/test_wprintf.out +++ b/tests/core/test_wprintf.out @@ -1,3 +1,16 @@ +fwprintf told us 7 +file size is 7 +str starts with 0x74 +str continues with 0x65 +str continues with 0x73 +format starts with 0x74 +fmt continues with 0x65 +fmt continues with 0x73 +vswprintf told us 36 +vswoutput st-rts with 0x74 +vsw continues with 0x65 +vsw continues with 0x73 +test string has 36 wide characters. Characters: a A Decimals: 1977 650000 Preceding with blanks: 1977 @@ -6,3 +19,25 @@ Some different radixes: 100 64 144 0x64 0144 floats: 3.14 +3e+00 3.141600E+00 Width trick: 10 A wide string +swprintf told us 20 +pre 84 +pre 104 +pre 101 +pre 32 +pre 104 +pre 97 +pre 108 +pre 102 +pre 32 +pre 111 +post 84 +post 104 +post 101 +post 32 +post 104 +post 97 +post 108 +post 102 +post 32 +post 111 +The half of 80 is 40, and the half of that is 20. diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js index a344fc35..7a8baef2 100644 --- a/tools/eliminator/asm-eliminator-test-output.js +++ b/tools/eliminator/asm-eliminator-test-output.js @@ -304,4 +304,510 @@ function binary(x) { memset(f(x)) | 0; +dmemset(f(x)); } +function cute($this, $outImage) { + $this = $this | 0; + $outImage = $outImage | 0; + var $retval = 0, $outImage_addr = 0, $width = 0, $height = 0, $bit_depth = 0, $color_type = 0, $data = 0, $bpl = 0, $y = 0, $i = 0, $y76 = 0, $p = 0, $end = 0, $this1 = 0, $call = 0, $call7 = 0, $call8 = 0, $3 = 0, $call17 = 0, $10 = 0, $call32 = 0, $call33 = 0, $17$0 = 0, $call34 = 0, $add_ptr = 0, $32 = 0, $call42 = 0, $35 = 0, $call45 = 0, $41 = 0, $call51 = 0, $43 = 0, $call55 = 0, $call57 = 0, $49 = 0, $call72 = 0, $call75 = 0, label = 0, setjmpLabel = 0, setjmpTable = 0, sp = 0; + sp = STACKTOP; + STACKTOP = STACKTOP + 32 | 0; + label = 1; + setjmpLabel = 0; + setjmpTable = STACKTOP; + STACKTOP = STACKTOP + 168 | 0; + HEAP32[setjmpTable >> 2] = 0; + while (1) switch (label | 0) { + case 1: + $width = sp | 0; + $height = sp + 8 | 0; + $bit_depth = sp + 16 | 0; + $color_type = sp + 24 | 0; + $outImage_addr = $outImage; + $this1 = $this; + if ((HEAP32[($this1 + 32 | 0) >> 2] | 0 | 0) == 3) { + label = 2; + break; + } else { + label = 3; + break; + } + case 2: + $retval = 0; + label = 37; + break; + case 3: + if ((HEAP32[($this1 + 32 | 0) >> 2] | 0 | 0) == 0) { + label = 4; + break; + } else { + label = 6; + break; + } + case 4: + $call = invoke_ii(900, $this1 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + if ($call) { + label = 6; + break; + } else { + label = 5; + break; + } + case 5: + HEAP32[($this1 + 32 | 0) >> 2] = 3; + $retval = 0; + label = 37; + break; + case 6: + HEAP32[($this1 + 28 | 0) >> 2] = 0; + $call7 = invoke_iiii(30, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, 2638 | 0, 156 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $call8 = _saveSetjmp($call7 | 0 | 0, label, setjmpTable) | 0; + label = 38; + break; + case 38: + if (($call8 | 0) != 0) { + label = 7; + break; + } else { + label = 10; + break; + } + case 7: + invoke_viii(640, $this1 + 16 | 0 | 0, $this1 + 20 | 0 | 0, $this1 + 24 | 0 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $3 = HEAP32[($this1 + 28 | 0) >> 2] | 0; + if (($3 | 0) == 0) { + label = 9; + break; + } else { + label = 8; + break; + } + case 8: + invoke_vi(926, $3 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + label = 9; + break; + case 9: + HEAP32[($this1 + 16 | 0) >> 2] = 0; + HEAP32[($this1 + 32 | 0) >> 2] = 3; + $retval = 0; + label = 37; + break; + case 10: + invoke_viiif(2, $outImage_addr | 0, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 20 | 0) >> 2] | 0 | 0, +(+HEAPF32[($this1 | 0) >> 2])); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $call17 = invoke_ii(832, $outImage_addr | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + if ($call17) { + label = 11; + break; + } else { + label = 14; + break; + } + case 11: + invoke_viii(640, $this1 + 16 | 0 | 0, $this1 + 20 | 0 | 0, $this1 + 24 | 0 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $10 = HEAP32[($this1 + 28 | 0) >> 2] | 0; + if (($10 | 0) == 0) { + label = 13; + break; + } else { + label = 12; + break; + } + case 12: + invoke_vi(926, $10 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + label = 13; + break; + case 13: + HEAP32[($this1 + 16 | 0) >> 2] = 0; + HEAP32[($this1 + 32 | 0) >> 2] = 3; + $retval = 0; + label = 37; + break; + case 14: + invoke_iiiiiiiiii(2, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 20 | 0) >> 2] | 0 | 0, $width | 0, $height | 0, $bit_depth | 0, $color_type | 0, 0 | 0, 0 | 0, 0 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $call32 = invoke_ii(850, $outImage_addr | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $data = $call32; + $call33 = invoke_ii(284, $outImage_addr | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $bpl = $call33; + $17$0 = invoke_iii(860, HEAP32[$height >> 2] | 0 | 0, 4 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $call34 = invoke_ii(550, (tempRet0 ? -1 : $17$0) | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + HEAP32[($this1 + 28 | 0) >> 2] = $call34; + $y = 0; + label = 15; + break; + case 15: + if ($y >>> 0 < (HEAP32[$height >> 2] | 0) >>> 0) { + label = 16; + break; + } else { + label = 18; + break; + } + case 16: + $add_ptr = $data + (Math_imul($y, $bpl) | 0) | 0; + HEAP32[((HEAP32[($this1 + 28 | 0) >> 2] | 0) + ($y << 2) | 0) >> 2] = $add_ptr; + label = 17; + break; + case 17: + $y = $y + 1 | 0; + label = 15; + break; + case 18: + invoke_vii(858, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 28 | 0) >> 2] | 0 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $32 = $outImage_addr; + $call42 = invoke_iii(690, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 20 | 0) >> 2] | 0 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + invoke_vii(1890, $32 | 0, $call42 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $35 = $outImage_addr; + $call45 = invoke_iii(256, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 20 | 0) >> 2] | 0 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + invoke_vii(2126, $35 | 0, $call45 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + HEAP32[($this1 + 32 | 0) >> 2] = 2; + invoke_vii(36, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 24 | 0) >> 2] | 0 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + invoke_vii(2752, $this1 | 0, HEAP32[($this1 + 24 | 0) >> 2] | 0 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $i = 0; + label = 19; + break; + case 19: + $41 = $i; + $call51 = invoke_ii(618, $this1 + 12 | 0 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + if (($41 | 0) < ($call51 - 1 | 0 | 0)) { + label = 20; + break; + } else { + label = 22; + break; + } + case 20: + $43 = $outImage_addr; + $call55 = invoke_iii(502, $this1 + 12 | 0 | 0, $i | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $call57 = invoke_iii(502, $this1 + 12 | 0 | 0, $i + 1 | 0 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + invoke_viii(550, $43 | 0, $call55 | 0, $call57 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + label = 21; + break; + case 21: + $i = $i + 2 | 0; + label = 19; + break; + case 22: + invoke_viii(640, $this1 + 16 | 0 | 0, $this1 + 20 | 0 | 0, $this1 + 24 | 0 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $49 = HEAP32[($this1 + 28 | 0) >> 2] | 0; + if (($49 | 0) == 0) { + label = 24; + break; + } else { + label = 23; + break; + } + case 23: + invoke_vi(926, $49 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + label = 24; + break; + case 24: + HEAP32[($this1 + 16 | 0) >> 2] = 0; + HEAP32[($this1 + 32 | 0) >> 2] = 0; + if ((HEAP32[$color_type >> 2] | 0 | 0) == 3) { + label = 25; + break; + } else { + label = 36; + break; + } + case 25: + $call72 = invoke_ii(926, $outImage_addr | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + if (($call72 | 0) == 3) { + label = 26; + break; + } else { + label = 36; + break; + } + case 26: + $call75 = invoke_ii(860, $outImage_addr | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $y76 = 0; + label = 27; + break; + case 27: + if (($y76 | 0) < (HEAP32[$height >> 2] | 0 | 0)) { + label = 28; + break; + } else { + label = 35; + break; + } + case 28: + $p = $data + (Math_imul($y76, $bpl) | 0) | 0; + $end = $p + (HEAP32[$width >> 2] | 0) | 0; + label = 29; + break; + case 29: + if ($p >>> 0 < $end >>> 0) { + label = 30; + break; + } else { + label = 33; + break; + } + case 30: + if (((HEAP8[$p] | 0) & 255 | 0) >= ($call75 | 0)) { + label = 31; + break; + } else { + label = 32; + break; + } + case 31: + HEAP8[$p] = 0; + label = 32; + break; + case 32: + $p = $p + 1 | 0; + label = 29; + break; + case 33: + label = 34; + break; + case 34: + $y76 = $y76 + 1 | 0; + label = 27; + break; + case 35: + label = 36; + break; + case 36: + $retval = 1; + label = 37; + break; + case 37: + STACKTOP = sp; + return $retval | 0; + case -1: + if ((setjmpLabel | 0) == 6) { + $call8 = threwValue; + label = 38; + } + __THREW__ = threwValue = 0; + break; + } + return 0; +} diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js index 4b45e4d4..ad1ed05e 100644 --- a/tools/eliminator/asm-eliminator-test.js +++ b/tools/eliminator/asm-eliminator-test.js @@ -378,5 +378,654 @@ function binary(x) { z = f(x); +dmemset(z); } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "looop8", "multiloop", "multiloop2", "tempDouble2", "watIf", "select2", "binary"] +function cute($this, $outImage) { + $this = $this | 0; + $outImage = $outImage | 0; + var $retval = 0, $this_addr = 0, $outImage_addr = 0, $width = 0, $height = 0, $bit_depth = 0, $color_type = 0, $data = 0, $bpl = 0, $y = 0, $i = 0, $color_table_size = 0, $y76 = 0, $p = 0, $end = 0, $this1 = 0, $state = 0, $0 = 0, $cmp = 0, $state2 = 0; + var $1 = 0, $cmp3 = 0, $call = 0, $state5 = 0, $row_pointers = 0, $png_ptr = 0, $2 = 0, $call7 = 0, $arraydecay = 0, $call8 = 0, $tobool = 0, $png_ptr10 = 0, $info_ptr = 0, $end_info = 0, $row_pointers11 = 0, $3 = 0, $isnull = 0, $4 = 0, $png_ptr12 = 0, $state13 = 0; + var $5 = 0, $png_ptr15 = 0, $6 = 0, $info_ptr16 = 0, $7 = 0, $gamma = 0, $8 = +0, $9 = 0, $call17 = 0, $png_ptr19 = 0, $info_ptr20 = 0, $end_info21 = 0, $row_pointers22 = 0, $10 = 0, $isnull23 = 0, $11 = 0, $png_ptr26 = 0, $state27 = 0, $png_ptr29 = 0, $12 = 0; + var $info_ptr30 = 0, $13 = 0, $call31 = 0, $14 = 0, $call32 = 0, $15 = 0, $call33 = 0, $16 = 0, $17$0 = 0, $17$1 = 0, $18 = 0, $19 = 0, $20 = 0, $call34 = 0, $21 = 0, $row_pointers35 = 0, $22 = 0, $23 = 0, $cmp36 = 0, $24 = 0; + var $25 = 0, $26 = 0, $mul = 0, $add_ptr = 0, $27 = 0, $row_pointers37 = 0, $28 = 0, $arrayidx = 0, $29 = 0, $inc = 0, $png_ptr38 = 0, $30 = 0, $row_pointers39 = 0, $31 = 0, $32 = 0, $png_ptr40 = 0, $33 = 0, $info_ptr41 = 0, $34 = 0, $call42 = 0; + var $35 = 0, $png_ptr43 = 0, $36 = 0, $info_ptr44 = 0, $37 = 0, $call45 = 0, $state46 = 0, $png_ptr47 = 0, $38 = 0, $end_info48 = 0, $39 = 0, $end_info49 = 0, $40 = 0, $41 = 0, $readTexts = 0, $42 = 0, $call51 = 0, $sub = 0, $cmp52 = 0, $43 = 0; + var $readTexts54 = 0, $44 = 0, $45 = 0, $call55 = 0, $readTexts56 = 0, $46 = 0, $47 = 0, $add = 0, $call57 = 0, $48 = 0, $add59 = 0, $png_ptr61 = 0, $info_ptr62 = 0, $end_info63 = 0, $row_pointers64 = 0, $49 = 0, $isnull65 = 0, $50 = 0, $png_ptr68 = 0, $state69 = 0; + var $51 = 0, $cmp70 = 0, $52 = 0, $call72 = 0, $cmp73 = 0, $53 = 0, $call75 = 0, $54 = 0, $55 = 0, $cmp78 = 0, $56 = 0, $57 = 0, $58 = 0, $mul80 = 0, $add_ptr81 = 0, $59 = 0, $60 = 0, $add_ptr82 = 0, $61 = 0, $62 = 0; + var $cmp83 = 0, $63 = 0, $64 = 0, $conv = 0, $65 = 0, $cmp84 = 0, $66 = 0, $67 = 0, $incdec_ptr = 0, $68 = 0, $inc88 = 0, $69 = 0, label = 0, setjmpLabel = 0, setjmpTable = 0; + var sp = 0; + sp = STACKTOP; + STACKTOP = STACKTOP + 32 | 0; + label = 1; + setjmpLabel = 0; + setjmpTable = STACKTOP; + STACKTOP = STACKTOP + 168 | 0; + HEAP32[setjmpTable >> 2] = 0; + while (1) switch (label | 0) { + case 1: + $width = sp | 0; + $height = sp + 8 | 0; + $bit_depth = sp + 16 | 0; + $color_type = sp + 24 | 0; + $this_addr = $this; + $outImage_addr = $outImage; + $this1 = $this_addr; + $state = $this1 + 32 | 0; + $0 = HEAP32[$state >> 2] | 0; + $cmp = ($0 | 0) == 3; + if ($cmp) { + label = 2; + break; + } else { + label = 3; + break; + } + case 2: + $retval = 0; + label = 37; + break; + case 3: + $state2 = $this1 + 32 | 0; + $1 = HEAP32[$state2 >> 2] | 0; + $cmp3 = ($1 | 0) == 0; + if ($cmp3) { + label = 4; + break; + } else { + label = 6; + break; + } + case 4: + $call = invoke_ii(900, $this1 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + if ($call) { + label = 6; + break; + } else { + label = 5; + break; + } + case 5: + $state5 = $this1 + 32 | 0; + HEAP32[$state5 >> 2] = 3; + $retval = 0; + label = 37; + break; + case 6: + $row_pointers = $this1 + 28 | 0; + HEAP32[$row_pointers >> 2] = 0; + $png_ptr = $this1 + 16 | 0; + $2 = HEAP32[$png_ptr >> 2] | 0; + $call7 = invoke_iiii(30, $2 | 0, 2638 | 0, 156 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $arraydecay = $call7 | 0; + $call8 = _saveSetjmp($arraydecay | 0, label, setjmpTable) | 0; + label = 38; + break; + case 38: + $tobool = ($call8 | 0) != 0; + if ($tobool) { + label = 7; + break; + } else { + label = 10; + break; + } + case 7: + $png_ptr10 = $this1 + 16 | 0; + $info_ptr = $this1 + 20 | 0; + $end_info = $this1 + 24 | 0; + invoke_viii(640, $png_ptr10 | 0, $info_ptr | 0, $end_info | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $row_pointers11 = $this1 + 28 | 0; + $3 = HEAP32[$row_pointers11 >> 2] | 0; + $isnull = ($3 | 0) == 0; + if ($isnull) { + label = 9; + break; + } else { + label = 8; + break; + } + case 8: + $4 = $3; + invoke_vi(926, $4 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + label = 9; + break; + case 9: + $png_ptr12 = $this1 + 16 | 0; + HEAP32[$png_ptr12 >> 2] = 0; + $state13 = $this1 + 32 | 0; + HEAP32[$state13 >> 2] = 3; + $retval = 0; + label = 37; + break; + case 10: + $5 = $outImage_addr; + $png_ptr15 = $this1 + 16 | 0; + $6 = HEAP32[$png_ptr15 >> 2] | 0; + $info_ptr16 = $this1 + 20 | 0; + $7 = HEAP32[$info_ptr16 >> 2] | 0; + $gamma = $this1 | 0; + $8 = +HEAPF32[$gamma >> 2]; + invoke_viiif(2, $5 | 0, $6 | 0, $7 | 0, +$8); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $9 = $outImage_addr; + $call17 = invoke_ii(832, $9 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + if ($call17) { + label = 11; + break; + } else { + label = 14; + break; + } + case 11: + $png_ptr19 = $this1 + 16 | 0; + $info_ptr20 = $this1 + 20 | 0; + $end_info21 = $this1 + 24 | 0; + invoke_viii(640, $png_ptr19 | 0, $info_ptr20 | 0, $end_info21 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $row_pointers22 = $this1 + 28 | 0; + $10 = HEAP32[$row_pointers22 >> 2] | 0; + $isnull23 = ($10 | 0) == 0; + if ($isnull23) { + label = 13; + break; + } else { + label = 12; + break; + } + case 12: + $11 = $10; + invoke_vi(926, $11 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + label = 13; + break; + case 13: + $png_ptr26 = $this1 + 16 | 0; + HEAP32[$png_ptr26 >> 2] = 0; + $state27 = $this1 + 32 | 0; + HEAP32[$state27 >> 2] = 3; + $retval = 0; + label = 37; + break; + case 14: + $png_ptr29 = $this1 + 16 | 0; + $12 = HEAP32[$png_ptr29 >> 2] | 0; + $info_ptr30 = $this1 + 20 | 0; + $13 = HEAP32[$info_ptr30 >> 2] | 0; + $call31 = invoke_iiiiiiiiii(2, $12 | 0, $13 | 0, $width | 0, $height | 0, $bit_depth | 0, $color_type | 0, 0 | 0, 0 | 0, 0 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $14 = $outImage_addr; + $call32 = invoke_ii(850, $14 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $data = $call32; + $15 = $outImage_addr; + $call33 = invoke_ii(284, $15 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $bpl = $call33; + $16 = HEAP32[$height >> 2] | 0; + $17$0 = invoke_iii(860, $16 | 0, 4 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $17$1 = tempRet0; + $18 = $17$1; + $19 = $17$0; + $20 = $18 ? -1 : $19; + $call34 = invoke_ii(550, $20 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $21 = $call34; + $row_pointers35 = $this1 + 28 | 0; + HEAP32[$row_pointers35 >> 2] = $21; + $y = 0; + label = 15; + break; + case 15: + $22 = $y; + $23 = HEAP32[$height >> 2] | 0; + $cmp36 = $22 >>> 0 < $23 >>> 0; + if ($cmp36) { + label = 16; + break; + } else { + label = 18; + break; + } + case 16: + $24 = $data; + $25 = $y; + $26 = $bpl; + $mul = Math_imul($25, $26) | 0; + $add_ptr = $24 + $mul | 0; + $27 = $y; + $row_pointers37 = $this1 + 28 | 0; + $28 = HEAP32[$row_pointers37 >> 2] | 0; + $arrayidx = $28 + ($27 << 2) | 0; + HEAP32[$arrayidx >> 2] = $add_ptr; + label = 17; + break; + case 17: + $29 = $y; + $inc = $29 + 1 | 0; + $y = $inc; + label = 15; + break; + case 18: + $png_ptr38 = $this1 + 16 | 0; + $30 = HEAP32[$png_ptr38 >> 2] | 0; + $row_pointers39 = $this1 + 28 | 0; + $31 = HEAP32[$row_pointers39 >> 2] | 0; + invoke_vii(858, $30 | 0, $31 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $32 = $outImage_addr; + $png_ptr40 = $this1 + 16 | 0; + $33 = HEAP32[$png_ptr40 >> 2] | 0; + $info_ptr41 = $this1 + 20 | 0; + $34 = HEAP32[$info_ptr41 >> 2] | 0; + $call42 = invoke_iii(690, $33 | 0, $34 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + invoke_vii(1890, $32 | 0, $call42 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $35 = $outImage_addr; + $png_ptr43 = $this1 + 16 | 0; + $36 = HEAP32[$png_ptr43 >> 2] | 0; + $info_ptr44 = $this1 + 20 | 0; + $37 = HEAP32[$info_ptr44 >> 2] | 0; + $call45 = invoke_iii(256, $36 | 0, $37 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + invoke_vii(2126, $35 | 0, $call45 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $state46 = $this1 + 32 | 0; + HEAP32[$state46 >> 2] = 2; + $png_ptr47 = $this1 + 16 | 0; + $38 = HEAP32[$png_ptr47 >> 2] | 0; + $end_info48 = $this1 + 24 | 0; + $39 = HEAP32[$end_info48 >> 2] | 0; + invoke_vii(36, $38 | 0, $39 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $end_info49 = $this1 + 24 | 0; + $40 = HEAP32[$end_info49 >> 2] | 0; + invoke_vii(2752, $this1 | 0, $40 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $i = 0; + label = 19; + break; + case 19: + $41 = $i; + $readTexts = $this1 + 12 | 0; + $42 = $readTexts; + $call51 = invoke_ii(618, $42 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $sub = $call51 - 1 | 0; + $cmp52 = ($41 | 0) < ($sub | 0); + if ($cmp52) { + label = 20; + break; + } else { + label = 22; + break; + } + case 20: + $43 = $outImage_addr; + $readTexts54 = $this1 + 12 | 0; + $44 = $readTexts54; + $45 = $i; + $call55 = invoke_iii(502, $44 | 0, $45 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $readTexts56 = $this1 + 12 | 0; + $46 = $readTexts56; + $47 = $i; + $add = $47 + 1 | 0; + $call57 = invoke_iii(502, $46 | 0, $add | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + invoke_viii(550, $43 | 0, $call55 | 0, $call57 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + label = 21; + break; + case 21: + $48 = $i; + $add59 = $48 + 2 | 0; + $i = $add59; + label = 19; + break; + case 22: + $png_ptr61 = $this1 + 16 | 0; + $info_ptr62 = $this1 + 20 | 0; + $end_info63 = $this1 + 24 | 0; + invoke_viii(640, $png_ptr61 | 0, $info_ptr62 | 0, $end_info63 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $row_pointers64 = $this1 + 28 | 0; + $49 = HEAP32[$row_pointers64 >> 2] | 0; + $isnull65 = ($49 | 0) == 0; + if ($isnull65) { + label = 24; + break; + } else { + label = 23; + break; + } + case 23: + $50 = $49; + invoke_vi(926, $50 | 0); + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + label = 24; + break; + case 24: + $png_ptr68 = $this1 + 16 | 0; + HEAP32[$png_ptr68 >> 2] = 0; + $state69 = $this1 + 32 | 0; + HEAP32[$state69 >> 2] = 0; + $51 = HEAP32[$color_type >> 2] | 0; + $cmp70 = ($51 | 0) == 3; + if ($cmp70) { + label = 25; + break; + } else { + label = 36; + break; + } + case 25: + $52 = $outImage_addr; + $call72 = invoke_ii(926, $52 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $cmp73 = ($call72 | 0) == 3; + if ($cmp73) { + label = 26; + break; + } else { + label = 36; + break; + } + case 26: + $53 = $outImage_addr; + $call75 = invoke_ii(860, $53 | 0) | 0; + if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) { + setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0; + if ((setjmpLabel | 0) > 0) { + label = -1; + break; + } else return 0 | 0; + } + __THREW__ = threwValue = 0; + $color_table_size = $call75; + $y76 = 0; + label = 27; + break; + case 27: + $54 = $y76; + $55 = HEAP32[$height >> 2] | 0; + $cmp78 = ($54 | 0) < ($55 | 0); + if ($cmp78) { + label = 28; + break; + } else { + label = 35; + break; + } + case 28: + $56 = $data; + $57 = $y76; + $58 = $bpl; + $mul80 = Math_imul($57, $58) | 0; + $add_ptr81 = $56 + $mul80 | 0; + $p = $add_ptr81; + $59 = $p; + $60 = HEAP32[$width >> 2] | 0; + $add_ptr82 = $59 + $60 | 0; + $end = $add_ptr82; + label = 29; + break; + case 29: + $61 = $p; + $62 = $end; + $cmp83 = $61 >>> 0 < $62 >>> 0; + if ($cmp83) { + label = 30; + break; + } else { + label = 33; + break; + } + case 30: + $63 = $p; + $64 = HEAP8[$63] | 0; + $conv = $64 & 255; + $65 = $color_table_size; + $cmp84 = ($conv | 0) >= ($65 | 0); + if ($cmp84) { + label = 31; + break; + } else { + label = 32; + break; + } + case 31: + $66 = $p; + HEAP8[$66] = 0; + label = 32; + break; + case 32: + $67 = $p; + $incdec_ptr = $67 + 1 | 0; + $p = $incdec_ptr; + label = 29; + break; + case 33: + label = 34; + break; + case 34: + $68 = $y76; + $inc88 = $68 + 1 | 0; + $y76 = $inc88; + label = 27; + break; + case 35: + label = 36; + break; + case 36: + $retval = 1; + label = 37; + break; + case 37: + $69 = $retval; + STACKTOP = sp; + return $69 | 0; + case -1: + if ((setjmpLabel | 0) == 6) { + $call8 = threwValue; + label = 38; + } + __THREW__ = threwValue = 0; + break; + } + return 0; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "looop8", "multiloop", "multiloop2", "tempDouble2", "watIf", "select2", "binary", "cute"] diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 5f0e17a5..4b1463eb 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -2245,7 +2245,7 @@ function eliminate(ast, memSafe) { var memoryInvalidated = false; var callsInvalidated = false; function track(name, value, defNode) { // add a potential that has just been defined to the tracked list, we hope to eliminate it - var usesGlobals = false, usesMemory = false, deps = {}, doesCall = false; + var usesGlobals = false, usesMemory = false, deps = {}, doesCall = false, hasDeps = false; var ignoreName = false; // one-time ignorings of names, as first op in sub and call traverse(value, function(node, type) { if (type === 'name') { @@ -2256,6 +2256,7 @@ function eliminate(ast, memSafe) { } if (!(name in potentials)) { // deps do not matter for potentials - they are defined once, so no complexity deps[name] = 1; + hasDeps = true; } } else { ignoreName = false; @@ -2277,6 +2278,7 @@ function eliminate(ast, memSafe) { usesMemory: usesMemory, defNode: defNode, deps: deps, + hasDeps: hasDeps, doesCall: doesCall }; globalsInvalidated = false; @@ -2349,7 +2351,7 @@ function eliminate(ast, memSafe) { function traverseInOrder(node, ignoreSub, ignoreName) { if (abort) return; //nesting++; // printErr-related - //printErr(spaces(2*(nesting+1)) + 'trav: ' + JSON.stringify(node).substr(0, 50) + ' : ' + keys(tracked) + ' : ' + [allowTracking, ignoreSub, ignoreName]); + //printErr(JSON.stringify(node).substr(0, 50) + ' : ' + keys(tracked) + ' : ' + [allowTracking, ignoreSub, ignoreName]); var type = node[0]; if (type === 'assign') { var target = node[2]; @@ -2525,6 +2527,8 @@ function eliminate(ast, memSafe) { traverseInOrder(node[3]); } else if (type === 'switch') { traverseInOrder(node[1]); + var originalTracked = {}; + for (var o in tracked) originalTracked[o] = 1; var cases = node[2]; for (var i = 0; i < cases.length; i++) { var c = cases[i]; @@ -2533,6 +2537,15 @@ function eliminate(ast, memSafe) { for (var j = 0; j < stats.length; j++) { traverseInOrder(stats[j]); } + // We cannot track from one switch case into another, undo all new trackings TODO: general framework here, use in if-else as well + for (var t in tracked) { + if (!(t in originalTracked)) { + var info = tracked[t]; + if (info.usesGlobals || info.usesMemory || info.hasDeps) { + delete tracked[t]; + } + } + } } } else { if (!(type in ABORTING_ELIMINATOR_SCAN_NODES)) { diff --git a/tools/shared.py b/tools/shared.py index 9cc10e60..1ee5cce8 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -345,7 +345,7 @@ def find_temp_directory(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.8.11' +EMSCRIPTEN_VERSION = '1.9.2' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT + '|' + get_clang_version() |