diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rwxr-xr-x | emcc | 21 | ||||
-rwxr-xr-x | emscripten.py | 10 | ||||
-rw-r--r-- | src/jsifier.js | 6 | ||||
-rw-r--r-- | src/library_browser.js | 2 | ||||
-rw-r--r-- | src/library_sdl.js | 222 | ||||
-rw-r--r-- | src/parseTools.js | 4 | ||||
-rw-r--r-- | src/runtime.js | 8 | ||||
-rw-r--r-- | src/utility.js | 10 | ||||
-rw-r--r-- | system/include/SDL/SDL_keycode.h | 3 | ||||
-rw-r--r-- | tests/cases/zeroextarg.ll | 22 | ||||
-rwxr-xr-x | tests/runner.py | 169 | ||||
-rw-r--r-- | tests/sdl_gfx_primitives.c | 46 | ||||
-rw-r--r-- | tests/sdl_gfx_primitives.png | bin | 0 -> 2357 bytes | |||
-rw-r--r-- | tests/sdl_rotozoom.c | 20 | ||||
-rw-r--r-- | tests/sdl_rotozoom.png | bin | 360054 -> 437956 bytes | |||
-rw-r--r-- | tools/autodebugger_js.py | 2 | ||||
-rw-r--r-- | tools/eliminator/eliminator-test-output.js | 3 | ||||
-rw-r--r-- | tools/js-optimizer.js | 532 | ||||
-rw-r--r-- | tools/shared.py | 6 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-last-output.js | 1 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-last.js | 1 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-outline-output.js | 570 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-outline.js | 606 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre-output.js | 4 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre.js | 7 |
26 files changed, 2110 insertions, 166 deletions
@@ -86,3 +86,4 @@ a license to everyone to use it as detailed in LICENSE.) * David Barksdale <david.barksdale@adcedosolutions.com> * Manfred Manik Nerurkar <nerurkar*at*made-apps.biz> (copyright owned by MADE, GmbH) * Joseph Gentle <me@josephg.com> +* Douglas T. Crosher <dtc-moz@scieneer.com> (copyright owned by Mozilla Founcation) @@ -522,14 +522,14 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG: open(tempout, 'w').write('//\n') src = None - for i in range(len(sys.argv)): - if sys.argv[i].endswith('.c'): + for arg in sys.argv: + if arg.endswith('.c'): try: - src = open(sys.argv[i]).read() - if debug_configure: open(tempout, 'a').write('============= ' + sys.argv[i] + '\n' + src + '\n=============\n\n') + src = open(arg).read() + if debug_configure: open(tempout, 'a').write('============= ' + arg + '\n' + src + '\n=============\n\n') except: pass - if sys.argv[i].endswith('.s'): + if arg.endswith('.s'): if debug_configure: open(tempout, 'a').write('(compiling .s assembly, must use clang\n') use_js = 0 @@ -826,7 +826,7 @@ try: newargs[i] = '' newargs[i+1] = '' elif newargs[i].startswith('--use-preload-cache'): - use_preload_cache = True; + use_preload_cache = True newargs[i] = '' elif newargs[i] == '--ignore-dynamic-linking': ignore_dynamic_linking = True @@ -952,7 +952,7 @@ try: if not prefix: continue if l.startswith(prefix): l = l[len(prefix):] - break; + break libs.append(l) newargs[i] = '' else: @@ -1121,9 +1121,8 @@ try: # Optimize source files if llvm_opts > 0: - for i in range(len(input_files)): - input_file = input_files[i] - if input_files[i].endswith(SOURCE_SUFFIXES): + for i, input_file in enumerate(input_files): + if input_file.endswith(SOURCE_SUFFIXES): temp_file = temp_files[i] logging.debug('optimizing %s with -O%d' % (input_file, llvm_opts)) shared.Building.llvm_opt(temp_file, llvm_opts) @@ -1214,7 +1213,7 @@ try: os.path.join('libc', 'gen', 'vwarn.c'), os.path.join('libc', 'gen', 'vwarnx.c'), os.path.join('libc', 'stdlib', 'strtod.c'), - ]; + ] return build_libc('libc.bc', libc_files) def apply_libc(need): diff --git a/emscripten.py b/emscripten.py index df0587f9..d9367566 100755 --- a/emscripten.py +++ b/emscripten.py @@ -163,10 +163,10 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, if DEBUG_CACHE and not out: dfpath = os.path.join(get_configuration().TEMP_DIR, "ems_" + shortkey) dfp = open(dfpath, 'w') - dfp.write(pre_input); - dfp.write("\n\n========================== settings_text\n\n"); - dfp.write(settings_text); - dfp.write("\n\n========================== libraries\n\n"); + dfp.write(pre_input) + dfp.write("\n\n========================== settings_text\n\n") + dfp.write(settings_text) + dfp.write("\n\n========================== libraries\n\n") dfp.write("\n".join(libraries)) dfp.close() print >>sys.stderr, ' cache miss, key data dumped to %s' % dfpath @@ -485,7 +485,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, global_vars = map(lambda g: g['name'], filter(lambda g: settings['NAMED_GLOBALS'] or g.get('external') or g.get('unIndexable'), forwarded_json['Variables']['globals'].values())) global_funcs = ['_' + key for key, value in forwarded_json['Functions']['libraryFunctions'].iteritems() if value != 2] def math_fix(g): - return g if not g.startswith('Math_') else g.split('_')[1]; + return g if not g.startswith('Math_') else g.split('_')[1] asm_global_funcs = ''.join([' var ' + g.replace('.', '_') + '=global.' + g + ';\n' for g in maths]) + \ ''.join([' var ' + g + '=env.' + math_fix(g) + ';\n' for g in basic_funcs + global_funcs]) asm_global_vars = ''.join([' var ' + g + '=env.' + g + '|0;\n' for g in basic_vars + global_vars]) + \ diff --git a/src/jsifier.js b/src/jsifier.js index 3f8c184c..82b78d0a 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1335,7 +1335,7 @@ function JSify(data, functionsOnly, givenFunctions) { makeFuncLineActor('alloca', function(item) { if (typeof item.allocatedIndex === 'number') { if (item.allocatedSize === 0) return ''; // This will not actually be shown - it's nativized - return asmCoercion(getFastValue('__stackBase__', '+', item.allocatedIndex.toString()), 'i32'); + return asmCoercion(getFastValue('sp', '+', item.allocatedIndex.toString()), 'i32'); } else { return RuntimeGenerator.stackAlloc(getFastValue(calcAllocatedSize(item.allocatedType), '*', item.allocatedNum)); } @@ -1479,8 +1479,8 @@ function JSify(data, functionsOnly, givenFunctions) { return inline.apply(null, args); // Warning: inlining does not prevent recalculation of the arguments. They should be simple identifiers } - if (ASM_JS) { - // remove unneeded arguments, which the asm sig can show us. this lets us alias memset with llvm.memset, we just + if (ASM_JS && ident.indexOf('llvm_') >= 0) { + // remove unneeded arguments in llvm intrinsic functions, which the asm sig can show us. this lets us alias memset with llvm.memset, we just // drop the final 2 args so things validate properly in asm var libsig = LibraryManager.library[simpleIdent + '__sig']; if (libsig) { diff --git a/src/library_browser.js b/src/library_browser.js index d9fd3ee5..822e99d6 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -84,7 +84,7 @@ mergeInto(LibraryManager.library, { var imagePlugin = {}; imagePlugin['canHandle'] = function(name) { - return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/.exec(name); + return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); }; imagePlugin['handle'] = function(byteArray, name, onload, onerror) { var b = null; diff --git a/src/library_sdl.js b/src/library_sdl.js index ce10f792..50405bb0 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -248,7 +248,7 @@ var LibrarySDL = { }, translateRGBAToCSSRGBA: function(r, g, b, a) { - return 'rgba(' + r + ',' + g + ',' + b + ',' + (a/255) + ')'; + return 'rgba(' + (r&0xff) + ',' + (g&0xff) + ',' + (b&0xff) + ',' + (a&0xff)/255 + ')'; }, translateRGBAToColor: function(r, g, b, a) { @@ -368,8 +368,48 @@ var LibrarySDL = { SDL.surfaces[surf] = null; }, + touchX:0, touchY: 0, + receiveEvent: function(event) { switch(event.type) { + case 'touchstart': + event.preventDefault(); + var touch = event.touches[0]; + touchX = touch.pageX; + touchY = touch.pageY; + var event = { + type: 'mousedown', + button: 0, + pageX: touchX, + pageY: touchY + }; + SDL.DOMButtons[0] = 1; + SDL.events.push(event); + break; + case 'touchmove': + event.preventDefault(); + var touch = event.touches[0]; + touchX = touch.pageX; + touchY = touch.pageY; + event = { + type: 'mousemove', + button: 0, + pageX: touchX, + pageY: touchY + }; + SDL.events.push(event); + break; + case 'touchend': + event.preventDefault(); + event = { + type: 'mouseup', + button: 0, + pageX: touchX, + pageY: touchY + }; + SDL.DOMButtons[0] = 0; + SDL.events.push(event); + break; case 'mousemove': if (Browser.pointerLock) { // workaround for firefox bug 750111 @@ -1029,6 +1069,7 @@ var LibrarySDL = { surfData.ctx.fillStyle = SDL.translateColorToCSSRGBA(color); surfData.ctx.fillRect(r.x, r.y, r.w, r.h); surfData.ctx.restore(); + return 0; }, SDL_BlitSurface__deps: ['SDL_UpperBlit'], @@ -1038,11 +1079,19 @@ var LibrarySDL = { zoomSurface: function(src, x, y, smooth) { var srcData = SDL.surfaces[src]; - var w = srcData.width*x; - var h = srcData.height*y; - var ret = SDL.makeSurface(w, h, srcData.flags, false, 'zoomSurface'); + var w = srcData.width * x; + var h = srcData.height * y; + var ret = SDL.makeSurface(Math.abs(w), Math.abs(h), srcData.flags, false, 'zoomSurface'); var dstData = SDL.surfaces[ret]; - dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h); + if (x >= 0 && y >= 0) dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h); + else { + dstData.ctx.save(); + dstData.ctx.scale(x < 0 ? -1 : 1, y < 0 ? -1 : 1); + dstData.ctx.drawImage(srcData.canvas, w < 0 ? w : 0, h < 0 ? h : 0, Math.abs(w), Math.abs(h)); + // XXX I think this should work according to the spec, but currently + // fails on FF: dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h); + dstData.ctx.restore(); + } return ret; }, @@ -1063,6 +1112,14 @@ var LibrarySDL = { SDL.surfaces[surf].alpha = alpha; }, + SDL_SetColorKey: function(surf, flag, key) { + // SetColorKey assigns one color to be rendered as transparent. I don't + // think the canvas API allows for anything like this, and iterating through + // each pixel to replace that color seems prohibitively expensive. + Runtime.warnOnce('SDL_SetColorKey is a no-op for performance reasons'); + return 0; + }, + SDL_GetTicks: function() { return Math.floor(Date.now() - SDL.startTime); }, @@ -1479,15 +1536,20 @@ var LibrarySDL = { }, Mix_HaltChannel: function(channel) { - var info = SDL.channels[channel]; - if (info.audio) { - info.audio.pause(); - info.audio = null; - } else { - Module.printErr('No Audio for channel: ' + channel); + function halt(channel) { + var info = SDL.channels[channel]; + if (info.audio) { + info.audio.pause(); + info.audio = null; + } + if (SDL.channelFinished) { + Runtime.getFuncWrapper(SDL.channelFinished, 'vi')(channel); + } } - if (SDL.channelFinished) { - Runtime.getFuncWrapper(SDL.channelFinished, 'vi')(channel); + if (channel != -1) { + halt(channel); + } else { + for (var i = 0; i < SDL.channels.length; ++i) halt(i); } return 0; }, @@ -1674,6 +1736,7 @@ var LibrarySDL = { }, TTF_RenderText_Blended: 'TTF_RenderText_Solid', // XXX ignore blending vs. solid TTF_RenderText_Shaded: 'TTF_RenderText_Solid', // XXX ignore blending vs. solid + TTF_RenderUTF8_Solid: 'TTF_RenderText_Solid', TTF_SizeText: function(font, text, w, h) { var fontData = SDL.fonts[font]; @@ -1698,35 +1761,114 @@ var LibrarySDL = { // SDL gfx + $SDL_gfx: { + drawRectangle: function(surf, x1, y1, x2, y2, action, cssColor) { + x1 = x1 << 16 >> 16; + y1 = y1 << 16 >> 16; + x2 = x2 << 16 >> 16; + y2 = y2 << 16 >> 16; + var surfData = SDL.surfaces[surf]; + assert(!surfData.locked); // but we could unlock and re-lock if we must.. + // TODO: if ctx does not change, leave as is, and also do not re-set xStyle etc. + var x = x1 < x2 ? x1 : x2; + var y = y1 < y2 ? y1 : y2; + var w = Math.abs(x2 - x1); + var h = Math.abs(y2 - y1); + surfData.ctx.save(); + surfData.ctx[action + 'Style'] = cssColor; + surfData.ctx[action + 'Rect'](x, y, w, h); + surfData.ctx.restore(); + }, + drawLine: function(surf, x1, y1, x2, y2, cssColor) { + x1 = x1 << 16 >> 16; + y1 = y1 << 16 >> 16; + x2 = x2 << 16 >> 16; + y2 = y2 << 16 >> 16; + var surfData = SDL.surfaces[surf]; + assert(!surfData.locked); // but we could unlock and re-lock if we must.. + surfData.ctx.save(); + surfData.ctx.strokeStyle = cssColor; + surfData.ctx.beginPath(); + surfData.ctx.moveTo(x1, y1); + surfData.ctx.lineTo(x2, y2); + surfData.ctx.stroke(); + surfData.ctx.restore(); + }, + // See http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + drawEllipse: function(surf, x, y, rx, ry, action, cssColor) { + x = x << 16 >> 16; + y = y << 16 >> 16; + rx = rx << 16 >> 16; + ry = ry << 16 >> 16; + var surfData = SDL.surfaces[surf]; + assert(!surfData.locked); // but we could unlock and re-lock if we must.. + + surfData.ctx.save(); + surfData.ctx.beginPath(); + surfData.ctx.translate(x, y); + surfData.ctx.scale(rx, ry); + surfData.ctx.arc(0, 0, 1, 0, 2 * Math.PI); + surfData.ctx.restore(); + + surfData.ctx.save(); + surfData.ctx[action + 'Style'] = cssColor; + surfData.ctx[action](); + surfData.ctx.restore(); + }, + // the gfx library uses something different from the rest of SDL... + translateColorToCSSRGBA: function(rgba) { + return 'rgba(' + (rgba>>>24) + ',' + (rgba>>16 & 0xff) + ',' + (rgba>>8 & 0xff) + ',' + (rgba&0xff) + ')'; + } + }, + + boxColor__deps: ['$SDL_gfx'], + boxColor: function(surf, x1, y1, x2, y2, color) { + return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'fill', SDL_gfx.translateColorToCSSRGBA(color)); + }, + + boxRGBA__deps: ['$SDL_gfx'], boxRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) { - var surfData = SDL.surfaces[surf]; - assert(!surfData.locked); // but we could unlock and re-lock if we must.. - // TODO: if ctx does not change, leave as is, and also do not re-set xStyle etc. - surfData.ctx.save(); - surfData.ctx.fillStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a); - surfData.ctx.fillRect(x1, y1, x2-x1, y2-y1); - surfData.ctx.restore(); + return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'fill', SDL.translateRGBAToCSSRGBA(r, g, b, a)); + }, + + rectangleColor__deps: ['$SDL_gfx'], + rectangleColor: function(surf, x1, y1, x2, y2, color) { + return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'stroke', SDL_gfx.translateColorToCSSRGBA(color)); }, + rectangleRGBA__deps: ['$SDL_gfx'], rectangleRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) { - var surfData = SDL.surfaces[surf]; - assert(!surfData.locked); // but we could unlock and re-lock if we must.. - surfData.ctx.save(); - surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a); - surfData.ctx.strokeRect(x1, y1, x2-x1, y2-y1); - surfData.ctx.restore(); + return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'stroke', SDL.translateRGBAToCSSRGBA(r, g, b, a)); + }, + + ellipseColor__deps: ['$SDL_gfx'], + ellipseColor: function(surf, x, y, rx, ry, color) { + return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'stroke', SDL_gfx.translateColorToCSSRGBA(color)); + }, + + ellipseRGBA__deps: ['$SDL_gfx'], + ellipseRGBA: function(surf, x, y, rx, ry, r, g, b, a) { + return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'stroke', SDL.translateRGBAToCSSRGBA(r, g, b, a)); + }, + + filledEllipseColor__deps: ['$SDL_gfx'], + filledEllipseColor: function(surf, x, y, rx, ry, color) { + return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'fill', SDL_gfx.translateColorToCSSRGBA(color)); }, + filledEllipseRGBA__deps: ['$SDL_gfx'], + filledEllipseRGBA: function(surf, x, y, rx, ry, r, g, b, a) { + return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'fill', SDL.translateRGBAToCSSRGBA(r, g, b, a)); + }, + + lineColor__deps: ['$SDL_gfx'], + lineColor: function(surf, x1, y1, x2, y2, color) { + return SDL_gfx.drawLine(surf, x1, y1, x2, y2, SDL_gfx.translateColorToCSSRGBA(color)); + }, + + lineRGBA__deps: ['$SDL_gfx'], lineRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) { - var surfData = SDL.surfaces[surf]; - assert(!surfData.locked); // but we could unlock and re-lock if we must.. - surfData.ctx.save(); - surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a); - surfData.ctx.beginPath(); - surfData.ctx.moveTo(x1, y1); - surfData.ctx.lineTo(x2, y2); - surfData.ctx.stroke(); - surfData.ctx.restore(); + return SDL_gfx.drawLine(surf, x1, y1, x2, y2, SDL.translateRGBAToCSSRGBA(r, g, b, a)); }, pixelRGBA__deps: ['boxRGBA'], @@ -1812,12 +1954,18 @@ var LibrarySDL = { return -1; }, + // Joysticks + + SDL_NumJoysticks: function() { return 0 }, + + SDL_JoystickOpen: function(deviceIndex) { return 0 }, + + SDL_JoystickGetButton: function(joystick, button) { return 0 }, + // Misc SDL_InitSubSystem: function(flags) { return 0 }, - SDL_NumJoysticks: function() { return 0 }, - SDL_RWFromFile: function(filename, mode) { return filename; // XXX We just forward the filename }, diff --git a/src/parseTools.js b/src/parseTools.js index dfd4b7ed..eb200c65 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -2222,9 +2222,9 @@ function processMathop(item) { // basic integer ops case 'add': return handleOverflow(getFastValue(idents[0], '+', idents[1], item.type), bits); case 'sub': return handleOverflow(getFastValue(idents[0], '-', idents[1], item.type), bits); - case 'sdiv': case 'udiv': return makeRounding(getFastValue(idents[0], '/', idents[1], item.type), bits, op[0] === 's'); + case 'sdiv': case 'udiv': return makeRounding(getFastValue(idents[0], '/', idents[1], item.type), bits, true); case 'mul': return getFastValue(idents[0], '*', idents[1], item.type); // overflow handling is already done in getFastValue for '*' - case 'urem': case 'srem': return makeRounding(getFastValue(idents[0], '%', idents[1], item.type), bits, op[0] === 's'); + case 'urem': case 'srem': return makeRounding(getFastValue(idents[0], '%', idents[1], item.type), bits, true); case 'or': { if (bits > 32) { assert(bits === 64, 'Too many bits for or: ' + bits); diff --git a/src/runtime.js b/src/runtime.js index e6d5f962..684f11e7 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -32,7 +32,7 @@ var RuntimeGenerator = { stackEnter: function(initial, force) { if (initial === 0 && SKIP_STACK_IN_SMALL && !force) return ''; - var ret = 'var __stackBase__ = ' + (ASM_JS ? '0; __stackBase__ = ' : '') + 'STACKTOP'; + var ret = 'var sp = ' + (ASM_JS ? '0; sp = ' : '') + 'STACKTOP'; if (initial > 0) ret += '; STACKTOP = (STACKTOP + ' + initial + ')|0'; if (USE_TYPED_ARRAYS == 2) { assert(initial % Runtime.STACK_ALIGN == 0); @@ -44,7 +44,7 @@ var RuntimeGenerator = { ret += '; (assert(' + asmCoercion('(STACKTOP|0) < (STACK_MAX|0)', 'i32') + ')|0)'; } if (false) { - ret += '; _memset(' + asmCoercion('__stackBase__', 'i32') + ', 0, ' + initial + ')'; + ret += '; _memset(' + asmCoercion('sp', 'i32') + ', 0, ' + initial + ')'; } return ret; }, @@ -53,9 +53,9 @@ var RuntimeGenerator = { if (initial === 0 && SKIP_STACK_IN_SMALL && !force) return ''; var ret = ''; if (SAFE_HEAP) { - ret += 'var i = __stackBase__; while ((i|0) < (STACKTOP|0)) { SAFE_HEAP_CLEAR(i|0); i = (i+1)|0 }'; + ret += 'var i = sp; while ((i|0) < (STACKTOP|0)) { SAFE_HEAP_CLEAR(i|0); i = (i+1)|0 }'; } - return ret += 'STACKTOP = __stackBase__'; + return ret += 'STACKTOP = sp'; }, // An allocation that cannot normally be free'd (except through sbrk, which once diff --git a/src/utility.js b/src/utility.js index b67e6c21..9cc8d3a3 100644 --- a/src/utility.js +++ b/src/utility.js @@ -298,12 +298,20 @@ function setIntersect(x, y) { var ret = {}; for (xx in x) { if (xx in y) { - ret[xx] = true; + ret[xx] = 0; } } return ret; } +function setUnion(x, y) { + var ret = set(keys(x)); + for (yy in y) { + ret[yy] = 0; + } + return ret; +} + function invertArray(x) { var ret = {}; for (var i = 0; i < x.length; i++) { diff --git a/system/include/SDL/SDL_keycode.h b/system/include/SDL/SDL_keycode.h index 472ca28e..84063b8b 100644 --- a/system/include/SDL/SDL_keycode.h +++ b/system/include/SDL/SDL_keycode.h @@ -310,7 +310,8 @@ enum SDLK_KBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN), SDLK_KBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP), SDLK_EJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT), - SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP) + SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP), + SDLK_LAST = SDL_SCANCODE_TO_KEYCODE(SDL_NUM_SCANCODES) }; /** diff --git a/tests/cases/zeroextarg.ll b/tests/cases/zeroextarg.ll new file mode 100644 index 00000000..25efb7ec --- /dev/null +++ b/tests/cases/zeroextarg.ll @@ -0,0 +1,22 @@ +; ModuleID = 'tests/hello_world.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +target triple = "i386-pc-linux-gnu" + +@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] + +define void @glSampleCoverage(float %18, i8 zeroext %invert) { +entry: + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] + ret void +} + +; [#uses=0] +define i32 @main() { +entry: + tail call void @glSampleCoverage(float 3.5, i8 zeroext 12) + ret i32 1 +} + +; [#uses=1] +declare i32 @printf(i8*, ...) + diff --git a/tests/runner.py b/tests/runner.py index a7f1ea66..b21eee08 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -10020,97 +10020,97 @@ finalizing 3 (global == 0) ''') # Generate tests for everything - def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0, typed_arrays=0, emcc_args=None, env='{}'): - exec(''' -class %s(T): - run_name = '%s' - env = %s + def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0, + typed_arrays=0, emcc_args=None, env=None): - def tearDown(self): - super(%s, self).tearDown() + if env is None: env = {} - for k, v in self.env.iteritems(): - del os.environ[k] + TT = type(fullname, (T,), dict(run_name = fullname, env = env)) + + def tearDown(self): + super(TT, self).tearDown() + + for k, v in self.env.iteritems(): + del os.environ[k] + + TT.tearDown = tearDown + + def setUp(self): + super(TT, self).setUp() + for k, v in self.env.iteritems(): + assert k not in os.environ, k + ' should not be in environment' + os.environ[k] = v + + global checked_sanity + if not checked_sanity: + print '(checking sanity from test runner)' # do this after we set env stuff + check_sanity(force=True) + checked_sanity = True + + Building.COMPILER_TEST_OPTS = ['-g'] + os.chdir(self.get_dir()) # Ensure the directory exists and go there + Building.COMPILER = compiler + + self.emcc_args = None if emcc_args is None else emcc_args[:] + if self.emcc_args is not None: + Settings.load(self.emcc_args) + Building.LLVM_OPTS = 0 + if '-O2' in self.emcc_args: + Building.COMPILER_TEST_OPTS = [] # remove -g in -O2 tests, for more coverage + #Building.COMPILER_TEST_OPTS += self.emcc_args + for arg in self.emcc_args: + if arg.startswith('-O'): + Building.COMPILER_TEST_OPTS.append(arg) # so bitcode is optimized too, this is for cpp to ll + else: + try: + key, value = arg.split('=') + Settings[key] = value # forward -s K=V + except: + pass + return + + # TODO: Move much of these to a init() function in shared.py, and reuse that + Settings.USE_TYPED_ARRAYS = typed_arrays + Settings.INVOKE_RUN = 1 + Settings.RELOOP = 0 # we only do them in the "o2" pass + Settings.MICRO_OPTS = embetter + Settings.QUANTUM_SIZE = quantum_size + Settings.ASSERTIONS = 1-embetter + Settings.SAFE_HEAP = 1-embetter + Settings.CHECK_OVERFLOWS = 1-embetter + Settings.CORRECT_OVERFLOWS = 1-embetter + Settings.CORRECT_SIGNS = 0 + Settings.CORRECT_ROUNDINGS = 0 + Settings.CORRECT_OVERFLOWS_LINES = CORRECT_SIGNS_LINES = CORRECT_ROUNDINGS_LINES = SAFE_HEAP_LINES = [] + Settings.CHECK_SIGNS = 0 #1-embetter + Settings.RUNTIME_TYPE_INFO = 0 + Settings.DISABLE_EXCEPTION_CATCHING = 0 + Settings.INCLUDE_FULL_LIBRARY = 0 + Settings.BUILD_AS_SHARED_LIB = 0 + Settings.RUNTIME_LINKED_LIBS = [] + Settings.EMULATE_UNALIGNED_ACCESSES = int(Settings.USE_TYPED_ARRAYS == 2 and Building.LLVM_OPTS == 2) + Settings.DOUBLE_MODE = 1 if Settings.USE_TYPED_ARRAYS and Building.LLVM_OPTS == 0 else 0 + Settings.PRECISE_I64_MATH = 0 + Settings.NAMED_GLOBALS = 0 if not embetter else 1 + + TT.setUp = setUp - def setUp(self): - super(%s, self).setUp() - - for k, v in self.env.iteritems(): - assert k not in os.environ, k + ' should not be in environment' - os.environ[k] = v - - global checked_sanity - if not checked_sanity: - print '(checking sanity from test runner)' # do this after we set env stuff - check_sanity(force=True) - checked_sanity = True - - Building.COMPILER_TEST_OPTS = ['-g'] - os.chdir(self.get_dir()) # Ensure the directory exists and go there - Building.COMPILER = %r - - self.emcc_args = %s - if self.emcc_args is not None: - Settings.load(self.emcc_args) - Building.LLVM_OPTS = 0 - if '-O2' in self.emcc_args: - Building.COMPILER_TEST_OPTS = [] # remove -g in -O2 tests, for more coverage - #Building.COMPILER_TEST_OPTS += self.emcc_args - for arg in self.emcc_args: - if arg.startswith('-O'): - Building.COMPILER_TEST_OPTS.append(arg) # so bitcode is optimized too, this is for cpp to ll - else: - try: - key, value = arg.split('=') - Settings[key] = value # forward -s K=V - except: - pass - return - - embetter = %d - quantum_size = %d - # TODO: Move much of these to a init() function in shared.py, and reuse that - Settings.USE_TYPED_ARRAYS = %d - Settings.INVOKE_RUN = 1 - Settings.RELOOP = 0 # we only do them in the "o2" pass - Settings.MICRO_OPTS = embetter - Settings.QUANTUM_SIZE = quantum_size - Settings.ASSERTIONS = 1-embetter - Settings.SAFE_HEAP = 1-embetter - Settings.CHECK_OVERFLOWS = 1-embetter - Settings.CORRECT_OVERFLOWS = 1-embetter - Settings.CORRECT_SIGNS = 0 - Settings.CORRECT_ROUNDINGS = 0 - Settings.CORRECT_OVERFLOWS_LINES = CORRECT_SIGNS_LINES = CORRECT_ROUNDINGS_LINES = SAFE_HEAP_LINES = [] - Settings.CHECK_SIGNS = 0 #1-embetter - Settings.RUNTIME_TYPE_INFO = 0 - Settings.DISABLE_EXCEPTION_CATCHING = 0 - Settings.INCLUDE_FULL_LIBRARY = 0 - Settings.BUILD_AS_SHARED_LIB = 0 - Settings.RUNTIME_LINKED_LIBS = [] - Settings.EMULATE_UNALIGNED_ACCESSES = int(Settings.USE_TYPED_ARRAYS == 2 and Building.LLVM_OPTS == 2) - Settings.DOUBLE_MODE = 1 if Settings.USE_TYPED_ARRAYS and Building.LLVM_OPTS == 0 else 0 - Settings.PRECISE_I64_MATH = 0 - Settings.NAMED_GLOBALS = 0 if not embetter else 1 - -TT = %s -''' % (fullname, fullname, env, fullname, fullname, compiler, str(emcc_args), embetter, quantum_size, typed_arrays, fullname)) return TT # Make one run with the defaults - exec('default = make_run("default", compiler=CLANG, emcc_args=[])') + default = make_run("default", compiler=CLANG, emcc_args=[]) # Make one run with -O1, with safe heap - exec('o1 = make_run("o1", compiler=CLANG, emcc_args=["-O1", "-s", "ASM_JS=0", "-s", "SAFE_HEAP=1"])') + o1 = make_run("o1", compiler=CLANG, emcc_args=["-O1", "-s", "ASM_JS=0", "-s", "SAFE_HEAP=1"]) # Make one run with -O2, but without closure (we enable closure in specific tests, otherwise on everything it is too slow) - exec('o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=0", "-s", "JS_CHUNK_SIZE=1024"])') + o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=0", "-s", "JS_CHUNK_SIZE=1024"]) # asm.js - exec('asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1", "-s", "CHECK_HEAP_ALIGN=1"])') - exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2"])') - exec('asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1"])') - exec('''asm2x86 = make_run("asm2x86", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "CHECK_HEAP_ALIGN=1"], env='{"EMCC_LLVM_TARGET": "i386-pc-linux-gnu"}')''') + asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1", "-s", "CHECK_HEAP_ALIGN=1"]) + asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2"]) + asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1"]) + asm2x86 = make_run("asm2x86", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "CHECK_HEAP_ALIGN=1"], env={"EMCC_LLVM_TARGET": "i386-pc-linux-gnu"}) # Make custom runs with various options for compiler, quantum, embetter, typed_arrays in [ @@ -10120,7 +10120,7 @@ TT = %s fullname = 's_0_%d%s%s' % ( embetter, '' if quantum == 4 else '_q' + str(quantum), '' if typed_arrays in [0, 1] else '_t' + str(typed_arrays) ) - exec('%s = make_run(fullname, %r,%r,%d,%d,%d)' % (fullname, fullname, compiler, embetter, quantum, typed_arrays)) + locals()[fullname] = make_run(fullname, fullname, compiler, embetter, quantum, typed_arrays) del T # T is just a shape for the specific subclasses, we don't test it itself @@ -11571,6 +11571,8 @@ f.close() ['asm', 'last']), (path_from_root('tools', 'test-js-optimizer-asm-relocate.js'), open(path_from_root('tools', 'test-js-optimizer-asm-relocate-output.js')).read(), ['asm', 'relocate']), + #(path_from_root('tools', 'test-js-optimizer-asm-outline.js'), open(path_from_root('tools', 'test-js-optimizer-asm-outline-output.js')).read(), + # ['asm', 'outline']), ]: print input output = Popen(listify(NODE_JS) + [path_from_root('tools', 'js-optimizer.js'), input] + passes, stdin=PIPE, stdout=PIPE).communicate()[0] @@ -13181,8 +13183,11 @@ Press any key to continue.''' self.btest('sdl_maprgba.c', reference='sdl_maprgba.png', reference_slack=3) def test_sdl_rotozoom(self): - shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'example.png')) - self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'example.png']) + shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) + self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'screenshot.png'], reference_slack=3) + + def test_sdl_gfx_primitives(self): + self.btest('sdl_gfx_primitives.c', reference='sdl_gfx_primitives.png', reference_slack=1) def test_sdl_canvas_palette_2(self): open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' diff --git a/tests/sdl_gfx_primitives.c b/tests/sdl_gfx_primitives.c new file mode 100644 index 00000000..db0c6181 --- /dev/null +++ b/tests/sdl_gfx_primitives.c @@ -0,0 +1,46 @@ +#include "SDL/SDL.h" +#include "SDL/SDL_gfxPrimitives.h" + +#ifdef EMSCRIPTEN +#include "emscripten.h" +#endif + +int main(int argc, char **argv) { + SDL_Init(SDL_INIT_VIDEO); + + const int width = 400; + const int height = 400; + SDL_Surface *screen = SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE); + boxColor(screen, 0, 0, width, height, 0xff); + + boxColor(screen, 0, 0, 98, 98, 0xff0000ff); + boxRGBA(screen, 100, 0, 198, 98, 0, 0, 0xff, 0xff); + // check that the x2 > x1 case is handled correctly + boxColor(screen, 298, 98, 200, 0, 0x00ff00ff); + boxColor(screen, 398, 98, 300, 0, 0xff0000ff); + + rectangleColor(screen, 0, 100, 98, 198, 0x000ffff); + rectangleRGBA(screen, 100, 100, 198, 198, 0xff, 0, 0, 0xff); + + ellipseColor(screen, 300, 150, 99, 49, 0x00ff00ff); + filledEllipseColor(screen, 100, 250, 99, 49, 0x00ff00ff); + filledEllipseRGBA(screen, 250, 300, 49, 99, 0, 0, 0xff, 0xff); + + lineColor(screen, 300, 200, 400, 300, 0x00ff00ff); + lineRGBA(screen, 300, 300, 400, 400, 0, 0xff, 0, 0xff); + + SDL_UpdateRect(screen, 0, 0, 0, 0); + +#ifndef EMSCRIPTEN + SDL_Event evt; + SDL_SaveBMP(screen, "native_output.bmp"); + while (1) { + if (SDL_PollEvent(&evt) != 0 && evt.type == SDL_QUIT) break; + SDL_Delay(33); + } +#endif + + SDL_Quit(); + + return 1; +} diff --git a/tests/sdl_gfx_primitives.png b/tests/sdl_gfx_primitives.png Binary files differnew file mode 100644 index 00000000..525b4f8f --- /dev/null +++ b/tests/sdl_gfx_primitives.png diff --git a/tests/sdl_rotozoom.c b/tests/sdl_rotozoom.c index b3970f6c..e81258d9 100644 --- a/tests/sdl_rotozoom.c +++ b/tests/sdl_rotozoom.c @@ -6,15 +6,18 @@ #include "emscripten.h" #endif +const int numSprites = 8; SDL_Surface *screen; -SDL_Surface *sprite[6]; +SDL_Surface *sprite[numSprites]; void mainloop() { int i; + int row = 0; SDL_Rect rect = { 0, 0, 100, 100 }; - for (i = 0; i < 6; i++) { + for (i = 0; i < numSprites; i++) { rect.x = i & 1 ? 200 : 0; - rect.y = i & 2 ? 200 : 0; + rect.y = row * 200; + row += i & 1; SDL_BlitSurface(sprite[i], 0, screen, &rect); SDL_UpdateRect(screen, 0, 0, 0, 0); } @@ -23,20 +26,27 @@ void mainloop() { int main(int argc, char **argv) { SDL_Init(SDL_INIT_VIDEO); - screen = SDL_SetVideoMode(400, 400, 32, SDL_SWSURFACE); + const int width = 400; + const int height = 200 * (numSprites + 1) / 2; + screen = SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE); + SDL_Rect rect = { 0, 0, width, height }; + SDL_FillRect(screen, &rect, SDL_MapRGBA(screen->format, 0, 0, 0, 0xff)); - sprite[0] = IMG_Load("example.png"); + sprite[0] = IMG_Load("screenshot.png"); sprite[1] = SDL_CreateRGBSurface(SDL_SWSURFACE, 100, 100, 32, 0xFF000000, 0xFF0000, 0xFF00, 0xFF); SDL_FillRect(sprite[1], 0, 0xA0A0A0A0); sprite[2] = zoomSurface(sprite[0], 0.5, 0.5, SMOOTHING_ON); sprite[3] = zoomSurface(sprite[1], 0.5, 0.5, SMOOTHING_ON); sprite[4] = rotozoomSurface(sprite[0], -20, 0.3, SMOOTHING_ON); sprite[5] = rotozoomSurface(sprite[1], 45, 0.5, SMOOTHING_ON); + sprite[6] = zoomSurface(sprite[0], -0.5, 0.5, SMOOTHING_ON); + sprite[7] = zoomSurface(sprite[0], -0.5, -0.5, SMOOTHING_ON); mainloop(); #ifndef EMSCRIPTEN SDL_Event evt; + SDL_SaveBMP(screen, "native_output.bmp"); while (1) { if (SDL_PollEvent(&evt) != 0 && evt.type == SDL_QUIT) break; //mainloop(); diff --git a/tests/sdl_rotozoom.png b/tests/sdl_rotozoom.png Binary files differindex 3ca8da70..5c5dec2f 100644 --- a/tests/sdl_rotozoom.png +++ b/tests/sdl_rotozoom.png diff --git a/tools/autodebugger_js.py b/tools/autodebugger_js.py index 3f8818c6..1de837f0 100644 --- a/tools/autodebugger_js.py +++ b/tools/autodebugger_js.py @@ -33,7 +33,7 @@ for i in range(len(lines)): (' else' not in lines[i-1] or '{' in lines[i-1]) and \ (' else' not in lines[i+1] or '{' in lines[i+1]): var = m.groups(1)[0].rstrip().split(' ')[-1] - if 'STACKTOP' not in lines[i] and 'stackBase' not in lines[i]: + if 'STACKTOP' not in lines[i] and 'sp' not in lines[i]: #lines[i] += ''' print("[%4d] %s = " + %s);''' % (i+1, var, var) lines[i] += ''' print("%s = " + %s);''' % (var, var) m = re.match('^ +HEAP.*$', lines[i]) diff --git a/tools/eliminator/eliminator-test-output.js b/tools/eliminator/eliminator-test-output.js index 801978ed..1a6506ed 100644 --- a/tools/eliminator/eliminator-test-output.js +++ b/tools/eliminator/eliminator-test-output.js @@ -2867,7 +2867,6 @@ function _inflate($strm, $flush) { var $retval_0; STACKTOP = __stackBase__; return $retval_0; - return null; } function _malloc($bytes) { var __label__; @@ -4482,7 +4481,6 @@ function _malloc($bytes) { } while (0); var $mem_0; return $mem_0; - return null; } function _mallocNoU($bytes) { var __label__; @@ -6097,7 +6095,6 @@ function _mallocNoU($bytes) { } while (0); var $mem_0; return $mem_0; - return null; } function asm(x, y) { x = +x; diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 91064de4..6987511c 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -136,6 +136,9 @@ var CONTROL_FLOW = set('do', 'while', 'for', 'if', 'switch'); var NAME_OR_NUM = set('name', 'num'); var ASSOCIATIVE_BINARIES = set('+', '*', '|', '&', '^'); +var BREAK_CAPTURERS = set('do', 'while', 'for', 'switch'); +var CONTINUE_CAPTURERS = LOOP; + var NULL_NODE = ['name', 'null']; var UNDEFINED_NODE = ['unary-prefix', 'void', ['num', 0]]; var TRUE_NODE = ['unary-prefix', '!', ['num', 0]]; @@ -405,7 +408,7 @@ function removeUnneededLabelSettings(ast) { // Various expression simplifications. Pre run before closure (where we still have metadata), Post run after. var USEFUL_BINARY_OPS = set('<<', '>>', '|', '&', '^'); -var COMPARE_OPS = set('<', '<=', '>', '>=', '==', '===', '!='); +var COMPARE_OPS = set('<', '<=', '>', '>=', '==', '===', '!=', '!=='); function simplifyExpressionsPre(ast) { // Simplify common expressions used to perform integer conversion operations @@ -504,6 +507,8 @@ function simplifyExpressionsPre(ast) { stack.push(1); } else if ((type === 'binary' && node[1] in SAFE_BINARY_OPS) || type === 'num' || type === 'name') { stack.push(0); // This node is safe in that it does not interfere with this optimization + } else if (type === 'unary-prefix' && node[1] === '~') { + stack.push(1); } else { stack.push(-1); // This node is dangerous! Give up if you see this before you see '1' } @@ -554,6 +559,12 @@ function simplifyExpressionsPre(ast) { } } } + } else if (type === 'binary' && node[1] === '^') { + // LLVM represents bitwise not as xor with -1. Translate it back to an actual bitwise not. + if (node[3][0] === 'unary-prefix' && node[3][1] === '-' && node[3][2][0] === 'num' && + node[3][2][1] === 1) { + return ['unary-prefix', '~', node[2]]; + } } else if (type === 'binary' && node[1] === '>>' && node[3][0] === 'num' && node[2][0] === 'binary' && node[2][1] === '<<' && node[2][3][0] === 'num' && node[2][2][0] === 'sub' && node[2][2][1][0] === 'name') { @@ -1523,10 +1534,15 @@ function unVarify(vars, ret) { // transform var x=1, y=2 etc. into (x=1, y=2), i var ASM_INT = 0; var ASM_DOUBLE = 1; -function detectAsmCoercion(node) { +function detectAsmCoercion(node, asmInfo) { // for params, +x vs x|0, for vars, 0.0 vs 0 if (node[0] === 'num' && node[1].toString().indexOf('.') >= 0) return ASM_DOUBLE; - return node[0] === 'unary-prefix' ? ASM_DOUBLE : ASM_INT; + if (node[0] === 'unary-prefix') return ASM_DOUBLE; + if (asmInfo && node[0] == 'name') { + if (node[1] in asmInfo.vars) return asmInfo.vars[node[1]]; + if (node[1] in asmInfo.params) return asmInfo.params[node[1]]; + } + return ASM_INT; } function makeAsmParamCoercion(param, type) { @@ -1537,6 +1553,11 @@ function makeAsmVarDef(v, type) { return [v, type === ASM_INT ? ['num', 0] : ['unary-prefix', '+', ['num', 0]]]; } +function getAsmType(asmInfo, name) { + if (name in asmInfo.vars) return asmInfo.vars[name]; + return asmInfo.params[name]; +} + function normalizeAsm(func) { //printErr('pre-normalize \n\n' + astToSrc(func) + '\n\n'); var data = { @@ -2507,6 +2528,8 @@ function eliminate(ast, memSafe) { if (type === 'stat') { node = node[1]; type = node[0]; + } else if (type == 'return' && i < stats.length-1) { + stats.length = i+1; // remove any code after a return } // Check for things that affect elimination if (type in ELIMINATION_SAFE_NODES) { @@ -2786,6 +2809,494 @@ function relocate(ast) { }); } +// Break up very large functions + +var NODES_WITHOUT_ELIMINATION_SENSITIVITY = set('name', 'num', 'binary', 'unary-prefix'); +var FAST_ELIMINATION_BINARIES = setUnion(setUnion(USEFUL_BINARY_OPS, COMPARE_OPS), set('+')); + +function outline(ast) { + function measureSize(ast) { + var size = 0; + traverse(ast, function() { + size++; + }); + return size; + } + + function aggressiveVariableElimination(func, asmData) { + // This removes as many variables as possible. This is often not the best thing because it increases + // code size, but it is far preferable to the risk of split functions needing to do more spilling. Specifically, + // it finds 'trivial' variables: ones with 1 definition, and that definition is not sensitive to any changes: it + // only depends on constants and local variables that are themselves trivial. We can unquestionably eliminate + // such variables in a trivial manner. + + var assignments = {}; + var appearances = {}; + var defs = {}; + var considered = {}; + + traverse(func, function(node, type) { + if (type == 'assign' && node[2][0] == 'name') { + var name = node[2][1]; + if (name in asmData.vars) { + assignments[name] = (assignments[name] || 0) + 1; + appearances[name] = (appearances[name] || 0) - 1; // this appearance is a definition, offset the counting later + defs[name] = node; + } else { + if (name in asmData.params) { + considered[name] = true; // this parameter is not ssa, it must be in a hand-optimized function, so it is not trivial + } + } + } else if (type == 'name') { + var name = node[1]; + if (name in asmData.vars) { + appearances[name] = (appearances[name] || 0) + 1; + } + } + }); + + var allTrivials = {}; // key of a trivial var => size of its (expanded) value, at least 1 + + // three levels of variables: + // 1. trivial: 1 def (or less), uses nothing sensitive, can be eliminated + // 2. safe: 1 def (or less), can be used in a trivial, but cannot itself be eliminated + // 3. sensitive: uses a global or memory or something else that prevents trivial elimination. + + function assessTriviality(name) { + // only care about vars with 0-1 assignments of (0 for parameters), and can ignore label (which is not explicitly initialized, but cannot be eliminated ever anyhow) + if (assignments[name] > 1 || (!(name in asmData.vars) && !(name in asmData.params)) || name == 'label') return false; + if (considered[name]) return allTrivials[name]; + considered[name] = true; + var sensitive = false; + var size = 0, originalSize = 0; + var def = defs[name]; + if (def) { + var value = def[3]; + originalSize = measureSize(value); + if (value) { + traverse(value, function recurseValue(node, type) { + var one = node[1]; + if (!(type in NODES_WITHOUT_ELIMINATION_SENSITIVITY)) { // || (type == 'binary' && !(one in FAST_ELIMINATION_BINARIES))) { + sensitive = true; + return true; + } + if (type == 'name' && !assessTriviality(one)) { + if (assignments[one] > 1 || (!(one in asmData.vars) && !(one in asmData.params))) { + sensitive = true; // directly using something sensitive + return true; + } // otherwise, not trivial, but at least safe. + } + // if this is a name, it must be a trivial variable (or a safe one) and we know its size + size += ((type == 'name') ? allTrivials[one] : 1) || 1; + }); + } + } + if (!sensitive) { + size = size || 1; + originalSize = originalSize || 1; + var factor = ((appearances[name] - 1) || 0) * (size - originalSize); // If no size change or just one appearance, always ok to trivially eliminate. otherwise, tradeoff + if (factor <= 12) { + allTrivials[name] = size; // trivial! + return true; + } + } + return false; + } + for (var name in asmData.vars) { + assessTriviality(name); + } + var trivials = {}; + + for (var name in allTrivials) { // from now on, ignore parameters + if (name in asmData.vars) trivials[name] = true; + } + + allTrivials = {}; + + var values = {}; + + function evaluate(name) { + var node = values[name]; + if (node) return node; + values[node] = null; // prevent infinite recursion + var def = defs[name]; + if (def) { + node = def[3]; + if (node[0] == 'name') { + var name2 = node[1]; + if (name2 in trivials) { + node = evaluate(name2); + } + } else { + traverse(node, function(node, type) { + if (type == 'name') { + var name2 = node[1]; + if (name2 in trivials) { + return evaluate(name2); + } + } + }); + } + values[name] = node; + } + return node; + } + + for (var name in trivials) { + evaluate(name); + } + + for (var name in trivials) { + var def = defs[name]; + if (def) { + def.length = 0; + def[0] = 'toplevel'; + def[1] = []; + } + delete asmData.vars[name]; + } + + // Perform replacements TODO: save list of uses objects before, replace directly, avoid extra traverse + traverse(func, function(node, type) { + if (type == 'name') { + var name = node[1]; + if (name in trivials) { + var value = values[name]; + if (!value) throw 'missing value: ' + [func[1], name, values[name]] + ' - faulty reliance on asm zero-init?'; + return copy(value); // must copy, or else the same object can be used multiple times + } + } + }); + } + + // Prepares information for spilling of local variables + function analyzeFunction(func, asmData) { + var stack = []; // list of variables, each gets 8 bytes + for (var name in asmData.params) { + stack.push(name); + } + for (var name in asmData.vars) { + stack.push(name); + } + asmData.stackPos = {}; + for (var i = 0; i < stack.length; i++) { + asmData.stackPos[stack[i]] = i*8; + } + // Reserve an extra two spots: one for control flow var, the other for control flow data + asmData.stackSize = (stack.length + 2)*8; + asmData.controlStackPos = asmData.stackSize - 16; + asmData.controlDataStackPos = asmData.stackSize - 8; + asmData.splitCounter = 0; + } + + // Analyze uses - reads and writes - of variables in part of the AST of a function + function analyzeCode(func, asmData, ast) { + var labels = {}; + var labelCounter = 1; // 0 means no label + + traverse(ast, function(node, type) { + if ((type == 'label' || type in LOOP_FLOW) && node[1] && !(node[1] in labels)) { + labels[node[1]] = labelCounter++; + } + }); + + var writes = {}; + var appearances = {}; + var hasReturn = false, hasBreak = false, hasContinue = false; + var breaks = {}; // set of labels we break or continue + var continues = {}; // to. '0' is an unlabeled one + var breakCapturers = 0; + var continueCapturers = 0; + + traverse(ast, function(node, type) { + if (type == 'assign' && node[2][0] == 'name') { + var name = node[2][1]; + if (name in asmData.vars || name in asmData.params) { + writes[name] = 0; + appearances[name] = (appearances[name] || 0) - 1; // this appearance is a definition, offset the counting later + } + } else if (type == 'name') { + var name = node[1]; + if (name in asmData.vars || name in asmData.params) { + appearances[name] = (appearances[name] || 0) + 1; + } + } else if (type == 'return') { + hasReturn = true; + } else if (type == 'break') { + var label = node[1] || 0; + if (!label && breakCapturers > 0) return; // no label, and captured + if (label && (label in labels)) return; // label, and defined in this code, so captured + breaks[label || 0] = 0; + hasBreak = true; + } else if (type == 'continue') { + var label = node[1] || 0; + if (!label && continueCapturers > 0) return; // no label, and captured + if (label && (label in labels)) return; // label, and defined in this code, so captured + continues[label || 0] = 0; + hasContinue = true; + } else { + if (type in BREAK_CAPTURERS) { + breakCapturers++; + } + if (type in CONTINUE_CAPTURERS) { + continueCapturers++; + } + } + }, function(node, type) { + if (type in BREAK_CAPTURERS) { + breakCapturers--; + } + if (type in CONTINUE_CAPTURERS) { + continueCapturers--; + } + }); + + var reads = {}; + + for (var name in appearances) { + if (appearances[name] > 0) reads[name] = 0; + } + + return { writes: writes, reads: reads, hasReturn: hasReturn, breaks: breaks, continues: continues, labels: labels }; + } + + function makeAssign(dst, src) { + return ['assign', true, dst, src]; + } + function makeStackAccess(type, pos) { // TODO: float64, not 32 + return ['sub', ['name', type == ASM_INT ? 'HEAP32' : 'HEAPF32'], ['binary', '>>', ['binary', '+', ['name', 'sp'], ['num', pos]], ['num', '2']]]; + } + function makeIf(cond, then, else_) { + var ret = ['if', cond, ['block', then]]; + if (else_) ret.push(['block', else_]); + return ret; + } + function makeComparison(left, comp, right) { + return ['binary', comp, left, right]; + } + + var CONTROL_BREAK = 1, CONTROL_BREAK_LABEL = 2, CONTROL_CONTINUE = 3, CONTROL_CONTINUE_LABEL = 4, CONTROL_RETURN_VOID = 5, CONTROL_RETURN_INT = 6, CONTROL_RETURN_DOUBLE = 7; + + var sizeToOutline = extraInfo.sizeToOutline; + var level = 0; + + function doOutline(func, asmData, stats, start, end) { + printErr(' do outline ' + [func[1], level, 'range:', start, end, 'of', stats.length]); + var code = stats.slice(start, end+1); + var newIdent = func[1] + '$' + (asmData.splitCounter++); + // add spills and reads before and after the call to the outlined code, and in the outlined code itself + var codeInfo = analyzeCode(func, asmData, code); + var reps = []; + for (var v in codeInfo.reads) { + if (v != 'sp') { + reps.push(['stat', ['assign', true, ['sub', ['name', getAsmType(asmData, v) == ASM_INT ? 'HEAP32' : 'HEAPF32'], ['binary', '>>', ['binary', '+', ['name', 'sp'], ['num', asmData.stackPos[v]]], ['num', '2']]], ['name', v]]]); + code.unshift(['stat', ['assign', true, ['name', v], ['sub', ['name', getAsmType(asmData, v) == ASM_INT ? 'HEAP32' : 'HEAPF32'], ['binary', '>>', ['binary', '+', ['name', 'sp'], ['num', asmData.stackPos[v]]], ['num', '2']]]]]); + } + } + reps.push(['stat', ['call', ['name', newIdent], [['name', 'sp']]]]); + for (var v in codeInfo.writes) { + reps.push(['stat', ['assign', true, ['name', v], ['sub', ['name', getAsmType(asmData, v) == ASM_INT ? 'HEAP32' : 'HEAPF32'], ['binary', '>>', ['binary', '+', ['name', 'sp'], ['num', asmData.stackPos[v]]], ['num', '2']]]]]); + code.push(['stat', ['assign', true, ['sub', ['name', getAsmType(asmData, v) == ASM_INT ? 'HEAP32' : 'HEAPF32'], ['binary', '>>', ['binary', '+', ['name', 'sp'], ['num', asmData.stackPos[v]]], ['num', '2']]], ['name', v]]]); + } + // Generate new function + if (codeInfo.hasReturn || codeInfo.hasBreak || codeInfo.hasContinue) { + // we need to capture all control flow using a top-level labeled one-time loop in the outlined function + code = [['label', 'OL', ['do', ['num', 0], ['block', code]]]]; + var breakCapturers = 0; + var continueCapturers = 0; + traverse(code, function(node, type) { + // replace all break/continue/returns with code to break out of the main one-time loop, and set the control data + if (type == 'return') { + var ret = ['break', 'OL']; + if (!node[1]) { + ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', CONTROL_RETURN_VOID]), ret]; + } else { + var type = detectAsmCoercion(node[1], asmData); + ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', type == ASM_INT ? CONTROL_RETURN_INT : CONTROL_RETURN_DOUBLE]), ret]; + ret = ['seq', makeAssign(makeStackAccess(type, asmData.controlDataStackPos), node[1]), ret]; + } + return ret; + } else if (type == 'break') { + var label = node[1] || 0; + if (label == 'OL') return; // this was just added before us, it is new replacement code + if (!label && breakCapturers > 0) return; // no label, and captured + if (label && (label in codeInfo.labels)) return; // label, and defined in this code, so captured + var ret = ['break', 'OL']; + ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', label ? CONTROL_BREAK_LABEL : CONTROL_BREAK]), ret]; + if (label) { + assert(label in codeInfo.labels, label + ' in ' + keys(codeInfo.labels)); + ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ['num', codeInfo.labels[label]]), ret]; + } + return ret; + } else if (type == 'continue') { + var label = node[1] || 0; + if (!label && continueCapturers > 0) return; // no label, and captured + if (label && (label in codeInfo.labels)) return; // label, and defined in this code, so captured + var ret = ['break', 'OL']; + ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', label ? CONTROL_CONTINUE_LABEL : CONTROL_CONTINUE]), ret]; + if (label) { + ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ['num', codeInfo.labels[label]]), ret]; + } + return ret; + } else { + if (type in BREAK_CAPTURERS) { + breakCapturers++; + } + if (type in CONTINUE_CAPTURERS) { + continueCapturers++; + } + } + }, function(node, type) { + if (type in BREAK_CAPTURERS) { + breakCapturers--; + } + if (type in CONTINUE_CAPTURERS) { + continueCapturers--; + } + }); + // read the control data at the callsite to the outlined function + if (codeInfo.hasReturn) { + reps.push(makeIf( + makeComparison(makeStackAccess(ASM_INT, asmData.controlStackPos), '==', ['num', CONTROL_RETURN_VOID]), + [['stat', ['return']]] + )); + reps.push(makeIf( + makeComparison(makeStackAccess(ASM_INT, asmData.controlStackPos), '==', ['num', CONTROL_RETURN_INT]), + [['stat', ['return', makeStackAccess(ASM_INT, asmData.controlDataStackPos)]]] + )); + reps.push(makeIf( + makeComparison(makeStackAccess(ASM_INT, asmData.controlStackPos), '==', ['num', CONTROL_RETURN_DOUBLE]), + [['stat', ['return', makeStackAccess(ASM_DOUBLE, asmData.controlDataStackPos)]]] + )); + } + if (codeInfo.hasBreak) { + reps.push(makeIf( + makeComparison(makeStackAccess(ASM_INT, asmData.controlStackPos), '==', ['num', CONTROL_BREAK]), + ['stat', ['break']] + )); + reps.push(makeIf( + makeComparison(makeStackAccess(ASM_INT, asmData.controlStackPos), '==', ['num', CONTROL_BREAK_LABEL]), + ['stat', ['break', makeStackAccess(ASM_INT, asmData.controlDataStackPos)]] // XXX here and below, need a switch overall possible labels + )); + } + if (codeInfo.hasContinue) { + reps.push(makeIf( + makeComparison(makeStackAccess(ASM_INT, asmData.controlStackPos), '==', ['num', CONTROL_CONTINUE]), + ['stat', ['break']] + )); + reps.push(makeIf( + makeComparison(makeStackAccess(ASM_INT, asmData.controlStackPos), '==', ['num', CONTROL_CONTINUE_LABEL]), + ['stat', ['continue', makeStackAccess(ASM_INT, asmData.controlDataStackPos)]] // XXX + )); + } + } + var newFunc = ['defun', newIdent, ['sp'], code]; + var newAsmData = { params: { sp: ASM_INT }, vars: {} }; + for (var v in codeInfo.reads) { + newAsmData.vars[v] = getAsmType(asmData, v); + } + for (var v in codeInfo.writes) { + newAsmData.vars[v] = getAsmType(asmData, v); + } + denormalizeAsm(newFunc, newAsmData); + // replace in stats + stats.splice.apply(stats, [start, end-start+1].concat(reps)); + return [newFunc]; + } + + function outlineStatements(func, asmData, stats, maxSize) { + level++; + if (measureSize(stats) < sizeToOutline) return; + var ret = []; + var sizeSeen = 0; + var end = stats.length-1; + var i = stats.length; + while (--i >= 0) { + var stat = stats[i]; + var size = measureSize(stat); + //printErr(level + ' size ' + [i, size]); + if (size >= sizeToOutline) { + // this by itself is big enough to inline, recurse into it and find statements to split on + var subStatements = null; + traverse(stat, function(node, type) { + if (type == 'block') { + if (measureSize(node) >= sizeToOutline) { + var subRet = outlineStatements(func, asmData, node[1], maxSize); + if (subRet && subRet.length > 0) ret.push.apply(ret, subRet); + } + return null; // do not recurse into children, outlineStatements will do so if necessary + } + }); + sizeSeen = 0; + continue; + } + sizeSeen += size; + // If this is big enough to outline, but no too big (if very close to the size of the full function, + // outlining is pointless; remove stats from the end to try to achieve the good case), then outline. + // Also, try to reduce the size if it is much larger than the hoped-for size + while ((sizeSeen > maxSize || sizeSeen > 2*sizeToOutline) && i < end) { + sizeSeen -= measureSize(stats[end]); + if (sizeSeen >= sizeToOutline) { + end--; + } else { + sizeSeen += measureSize(stats[end]); // abort, this took away too much + break; + } + } + if (sizeSeen >= sizeToOutline && sizeSeen <= maxSize) { + ret.push.apply(ret, doOutline(func, asmData, stats, i, end)); // outline [i, .. ,end] inclusive + sizeSeen = 0; + end = i-1; + } + } + level--; + return ret; + } + + // + + if (ast[0] !== 'toplevel') { + assert(ast[0] == 'defun'); + ast = ['toplevel', [ast]]; + } + + var funcs = ast[1]; + + var more = true; + while (more) { + more = false; + + var newFuncs = []; + + funcs.forEach(function(func) { + var asmData = normalizeAsm(func); + var size = measureSize(func); + if (size >= sizeToOutline) { + aggressiveVariableElimination(func, asmData); + analyzeFunction(func, asmData); + var ret = outlineStatements(func, asmData, getStatements(func), 0.5*size); + if (ret && ret.length > 0) newFuncs.push.apply(newFuncs, ret); + } + denormalizeAsm(func, asmData); + }); + + // TODO: control flow: route returns and breaks. outlined code should have all breaks/continues/returns break into the outermost scope, + // after setting a state variable, etc. + + if (newFuncs.length > 0) { + // We have outlined. Add stack support: header in which we allocate enough stack space TODO + // If sp was not present before, add it and before each return, pop the stack. also a final pop if not ending with a return TODO + // (none of this should be done in inner functions, of course, just the original) + + // add new functions to the toplevel, or create a toplevel if there isn't one + ast[1].push.apply(ast[1], newFuncs); + + funcs = newFuncs; + more = true; + } + } +} + // Last pass utilities // Change +5 to DOT$ZERO(5). We then textually change 5 to 5.0 (uglify's ast cannot differentiate between 5 and 5.0 directly) @@ -2811,12 +3322,13 @@ function fixDotZero(js) { }); } -function asmLoopOptimizer(ast) { +function asmLastOpts(ast) { traverseGeneratedFunctions(ast, function(fun) { - // This is at the end of the pipeline, we can assume all other optimizations are done, and we modify loops - // into shapes that might confuse other passes traverse(fun, function(node, type) { if (type === 'while' && node[1][0] === 'num' && node[1][1] === 1 && node[2][0] === 'block') { + // This is at the end of the pipeline, we can assume all other optimizations are done, and we modify loops + // into shapes that might confuse other passes + // while (1) { .. if (..) { break } } ==> do { .. } while(..) var stats = node[2][1]; var last = stats[stats.length-1]; @@ -2844,6 +3356,11 @@ function asmLoopOptimizer(ast) { node[1] = simplifyNotCompsDirect(['unary-prefix', '!', conditionToBreak]); return node; } + } else if (type == 'binary' && node[1] == '&' && node[3][0] == 'unary-prefix' && node[3][1] == '-' && node[3][2][0] == 'num' && node[3][2][1] == 1) { + // Change &-1 into |0, at this point the hint is no longer needed + node[1] = '|'; + node[3] = node[3][2]; + node[3][1] = 0; } }); }); @@ -2870,6 +3387,7 @@ var passes = { eliminateMemSafe: eliminateMemSafe, minifyGlobals: minifyGlobals, relocate: relocate, + outline: outline, minifyWhitespace: function() { minifyWhitespace = true }, noPrintMetadata: function() { printMetadata = false }, asm: function() { asm = true }, @@ -2901,7 +3419,7 @@ arguments_.slice(1).forEach(function(arg) { passes[arg](ast); }); if (asm && last) { - asmLoopOptimizer(ast); // TODO: move out of last, to make last faster when done later (as in side modules) + asmLastOpts(ast); // TODO: move out of last, to make last faster when done later (as in side modules) prepDotZero(ast); } var js = astToSrc(ast, minifyWhitespace), old; diff --git a/tools/shared.py b/tools/shared.py index 46245fd1..0351a736 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -257,7 +257,7 @@ def check_clang_version(): def check_llvm_version(): try: - check_clang_version(); + check_clang_version() except Exception, e: logging.warning('Could not verify LLVM version: %s' % str(e)) @@ -1196,7 +1196,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e opts.append('-jump-threading') opts.append('-correlated-propagation') opts.append('-dse') - #addExtensionsToPM(EP_ScalarOptimizerLate, MPM); + #addExtensionsToPM(EP_ScalarOptimizerLate, MPM) opts.append('-adce') opts.append('-simplifycfg') @@ -1300,7 +1300,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e '-O' + str(opt_level), '--closure', '0'], raw) f = open(relooper, 'w') f.write("// Relooper, (C) 2012 Alon Zakai, MIT license, https://github.com/kripken/Relooper\n") - f.write("var Relooper = (function() {\n"); + f.write("var Relooper = (function() {\n") f.write(open(raw).read()) f.write('\n return Module.Relooper;\n') f.write('})();\n') diff --git a/tools/test-js-optimizer-asm-last-output.js b/tools/test-js-optimizer-asm-last-output.js index 0f95d544..f850b18f 100644 --- a/tools/test-js-optimizer-asm-last-output.js +++ b/tools/test-js-optimizer-asm-last-output.js @@ -30,6 +30,7 @@ function finall(x) { a = -999999984306749400.0; a = -999999984306749400.0; a = -0xde0b6b000000000; + f(g() | 0); return 12.0e10; } function looop() { diff --git a/tools/test-js-optimizer-asm-last.js b/tools/test-js-optimizer-asm-last.js index 05e1049e..1d39b1a6 100644 --- a/tools/test-js-optimizer-asm-last.js +++ b/tools/test-js-optimizer-asm-last.js @@ -30,6 +30,7 @@ function finall(x) { a = +-0xde0b6b000000000; a = -+0xde0b6b000000000; a = -0xde0b6b000000000; + f(g() & -1); return +12e10; } function looop() { diff --git a/tools/test-js-optimizer-asm-outline-output.js b/tools/test-js-optimizer-asm-outline-output.js new file mode 100644 index 00000000..c54fc346 --- /dev/null +++ b/tools/test-js-optimizer-asm-outline-output.js @@ -0,0 +1,570 @@ +function linear() { + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); +} +function _free($mem) { + $mem = $mem | 0; + var $5 = 0, $10 = 0, $16 = 0, $21 = 0, $25 = 0, $26 = 0, $37 = 0, $40 = 0, $_pre_phi307 = 0, $69 = 0, $72 = 0, $75 = 0, $80 = 0, $95 = 0, $100 = 0, $RP_0 = 0, $R_0 = 0, $102 = 0, $103 = 0, $106 = 0, $107 = 0, $R_1 = 0, $120 = 0, $151 = 0, $164 = 0, $psize_0 = 0, $p_0 = 0, $189 = 0, $194 = 0, $204 = 0, $220 = 0, $227 = 0, $233 = 0, $236 = 0, $_pre_phi305 = 0, $267 = 0, $270 = 0, $273 = 0, $278 = 0, $294 = 0, $299 = 0, $RP9_0 = 0, $R7_0 = 0, $301 = 0, $302 = 0, $305 = 0, $306 = 0, $R7_1 = 0, $320 = 0, $351 = 0, $364 = 0, $psize_1 = 0, $390 = 0, $396 = 0, $404 = 0, $_pre_phi = 0, $F16_0 = 0, $414 = 0, $415 = 0, $428 = 0, $436 = 0, $I18_0 = 0, $443 = 0, $447 = 0, $448 = 0, $463 = 0, $T_0 = 0, $K19_0 = 0, $472 = 0, $473 = 0, $486 = 0, $487 = 0, $489 = 0, $501 = 0, $sp_0_in_i = 0, $sp_0_i = 0, label = 0, sp = 0; + sp = STACKTOP; + if (($mem | 0) == 0) { + STACKTOP = sp; + return; + } + $5 = HEAP32[24] | 0; + if (($mem - 8 | 0) >>> 0 < $5 >>> 0) { + _abort(); + } + $10 = HEAP32[$mem - 4 >> 2] | 0; + if (($10 & 3 | 0) == 1) { + _abort(); + } + $16 = $mem + (($10 & -8) - 8) | 0; + L621 : do { + if (($10 & 1 | 0) == 0) { + $21 = HEAP32[($mem - 8 | 0) >> 2] | 0; + if (($10 & 3 | 0) == 0) { + return; + } + $25 = $mem + (-8 - $21 | 0) | 0; + $26 = $21 + ($10 & -8) | 0; + if (($mem + (-8 - $21 | 0) | 0) >>> 0 < $5 >>> 0) { + _abort(); + } + if (($25 | 0) == (HEAP32[25] | 0)) { + if ((HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] & 3 | 0) != 3) { + $p_0 = $25; + $psize_0 = $26; + break; + } + HEAP32[22] = $26; + HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] = HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] & -2; + HEAP32[$mem + ((-8 - $21 | 0) + 4) >> 2] = $26 | 1; + HEAP32[($mem + (($10 & -8) - 8) | 0) >> 2] = $26; + return; + } + if ($21 >>> 0 < 256) { + $37 = HEAP32[$mem + ((-8 - $21 | 0) + 8) >> 2] | 0; + $40 = HEAP32[$mem + ((-8 - $21 | 0) + 12) >> 2] | 0; + do { + if (($37 | 0) != (120 + ($21 >>> 3 << 1 << 2) | 0 | 0)) { + if ($37 >>> 0 < $5 >>> 0) { + _abort(); + } + if ((HEAP32[$37 + 12 >> 2] | 0) == ($25 | 0)) { + break; + } + _abort(); + } + } while (0); + if (($40 | 0) == ($37 | 0)) { + HEAP32[20] = HEAP32[20] & (1 << ($21 >>> 3) ^ -1); + $p_0 = $25; + $psize_0 = $26; + break; + } + do { + if (($40 | 0) == (120 + ($21 >>> 3 << 1 << 2) | 0 | 0)) { + $_pre_phi307 = $40 + 8 | 0; + } else { + if ($40 >>> 0 < $5 >>> 0) { + _abort(); + } + if ((HEAP32[($40 + 8 | 0) >> 2] | 0) == ($25 | 0)) { + $_pre_phi307 = $40 + 8 | 0; + break; + } + _abort(); + } + } while (0); + HEAP32[$37 + 12 >> 2] = $40; + HEAP32[$_pre_phi307 >> 2] = $37; + $p_0 = $25; + $psize_0 = $26; + break; + } + $69 = $mem + (-8 - $21 | 0) | 0; + $72 = HEAP32[$mem + ((-8 - $21 | 0) + 24) >> 2] | 0; + $75 = HEAP32[$mem + ((-8 - $21 | 0) + 12) >> 2] | 0; + do { + if (($75 | 0) == ($69 | 0)) { + $95 = HEAP32[($mem + ((-8 - $21 | 0) + 20) | 0) >> 2] | 0; + if (($95 | 0) == 0) { + $100 = HEAP32[($mem + ((-8 - $21 | 0) + 16) | 0) >> 2] | 0; + if (($100 | 0) == 0) { + $R_1 = 0; + break; + } else { + $R_0 = $100; + $RP_0 = $mem + ((-8 - $21 | 0) + 16) | 0; + } + } else { + $R_0 = $95; + $RP_0 = $mem + ((-8 - $21 | 0) + 20) | 0; + } + while (1) { + $102 = $R_0 + 20 | 0; + $103 = HEAP32[$102 >> 2] | 0; + if (($103 | 0) != 0) { + $R_0 = $103; + $RP_0 = $102; + continue; + } + $106 = $R_0 + 16 | 0; + $107 = HEAP32[$106 >> 2] | 0; + if (($107 | 0) == 0) { + break; + } else { + $R_0 = $107; + $RP_0 = $106; + } + } + if ($RP_0 >>> 0 < $5 >>> 0) { + _abort(); + } else { + HEAP32[$RP_0 >> 2] = 0; + $R_1 = $R_0; + break; + } + } else { + $80 = HEAP32[$mem + ((-8 - $21 | 0) + 8) >> 2] | 0; + if ($80 >>> 0 < $5 >>> 0) { + _abort(); + } + if ((HEAP32[($80 + 12 | 0) >> 2] | 0) != ($69 | 0)) { + _abort(); + } + if ((HEAP32[($75 + 8 | 0) >> 2] | 0) == ($69 | 0)) { + HEAP32[($80 + 12 | 0) >> 2] = $75; + HEAP32[($75 + 8 | 0) >> 2] = $80; + $R_1 = $75; + break; + } else { + _abort(); + } + } + } while (0); + if (($72 | 0) == 0) { + $p_0 = $25; + $psize_0 = $26; + break; + } + $120 = 384 + (HEAP32[($mem + ((-8 - $21 | 0) + 28) | 0) >> 2] << 2) | 0; + do { + if (($69 | 0) == (HEAP32[$120 >> 2] | 0)) { + HEAP32[$120 >> 2] = $R_1; + if (($R_1 | 0) != 0) { + break; + } + HEAP32[21] = HEAP32[21] & (1 << HEAP32[($mem + ((-8 - $21 | 0) + 28) | 0) >> 2] ^ -1); + $p_0 = $25; + $psize_0 = $26; + break L621; + } else { + if ($72 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + if ((HEAP32[($72 + 16 | 0) >> 2] | 0) == ($69 | 0)) { + HEAP32[($72 + 16 | 0) >> 2] = $R_1; + } else { + HEAP32[$72 + 20 >> 2] = $R_1; + } + if (($R_1 | 0) == 0) { + $p_0 = $25; + $psize_0 = $26; + break L621; + } + } + } while (0); + if ($R_1 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + HEAP32[$R_1 + 24 >> 2] = $72; + $151 = HEAP32[$mem + ((-8 - $21 | 0) + 16) >> 2] | 0; + do { + if (($151 | 0) != 0) { + if ($151 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$R_1 + 16 >> 2] = $151; + HEAP32[$151 + 24 >> 2] = $R_1; + break; + } + } + } while (0); + $164 = HEAP32[$mem + ((-8 - $21 | 0) + 20) >> 2] | 0; + if (($164 | 0) == 0) { + $p_0 = $25; + $psize_0 = $26; + break; + } + if ($164 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$R_1 + 20 >> 2] = $164; + HEAP32[$164 + 24 >> 2] = $R_1; + $p_0 = $25; + $psize_0 = $26; + break; + } + } else { + $p_0 = $mem - 8 | 0; + $psize_0 = $10 & -8; + } + } while (0); + $189 = $p_0; + if ($189 >>> 0 >= ($mem + (($10 & -8) - 8) | 0) >>> 0) { + _abort(); + } + $194 = HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] | 0; + if (($194 & 1 | 0) == 0) { + _abort(); + } + do { + if (($194 & 2 | 0) == 0) { + if (($16 | 0) == (HEAP32[26] | 0)) { + $204 = (HEAP32[23] | 0) + $psize_0 | 0; + HEAP32[23] = $204; + HEAP32[26] = $p_0; + HEAP32[$p_0 + 4 >> 2] = $204 | 1; + if (($p_0 | 0) == (HEAP32[25] | 0)) { + HEAP32[25] = 0; + HEAP32[22] = 0; + } + if ($204 >>> 0 <= (HEAP32[27] | 0) >>> 0) { + return; + } + _sys_trim(0) | 0; + return; + } + if (($16 | 0) == (HEAP32[25] | 0)) { + $220 = (HEAP32[22] | 0) + $psize_0 | 0; + HEAP32[22] = $220; + HEAP32[25] = $p_0; + HEAP32[$p_0 + 4 >> 2] = $220 | 1; + HEAP32[$189 + $220 >> 2] = $220; + return; + } + $227 = ($194 & -8) + $psize_0 | 0; + L726 : do { + if ($194 >>> 0 < 256) { + $233 = HEAP32[$mem + ($10 & -8) >> 2] | 0; + $236 = HEAP32[$mem + ($10 & -8 | 4) >> 2] | 0; + do { + if (($233 | 0) != (120 + ($194 >>> 3 << 1 << 2) | 0 | 0)) { + if ($233 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + if ((HEAP32[$233 + 12 >> 2] | 0) == ($16 | 0)) { + break; + } + _abort(); + } + } while (0); + if (($236 | 0) == ($233 | 0)) { + HEAP32[20] = HEAP32[20] & (1 << ($194 >>> 3) ^ -1); + break; + } + do { + if (($236 | 0) == (120 + ($194 >>> 3 << 1 << 2) | 0 | 0)) { + $_pre_phi305 = $236 + 8 | 0; + } else { + if ($236 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + if ((HEAP32[($236 + 8 | 0) >> 2] | 0) == ($16 | 0)) { + $_pre_phi305 = $236 + 8 | 0; + break; + } + _abort(); + } + } while (0); + HEAP32[$233 + 12 >> 2] = $236; + HEAP32[$_pre_phi305 >> 2] = $233; + } else { + $267 = $mem + (($10 & -8) - 8) | 0; + $270 = HEAP32[$mem + (($10 & -8) + 16) >> 2] | 0; + $273 = HEAP32[$mem + ($10 & -8 | 4) >> 2] | 0; + do { + if (($273 | 0) == ($267 | 0)) { + $294 = HEAP32[($mem + (($10 & -8) + 12) | 0) >> 2] | 0; + if (($294 | 0) == 0) { + $299 = HEAP32[($mem + (($10 & -8) + 8) | 0) >> 2] | 0; + if (($299 | 0) == 0) { + $R7_1 = 0; + break; + } else { + $R7_0 = $299; + $RP9_0 = $mem + (($10 & -8) + 8) | 0; + } + } else { + $R7_0 = $294; + $RP9_0 = $mem + (($10 & -8) + 12) | 0; + } + while (1) { + $301 = $R7_0 + 20 | 0; + $302 = HEAP32[$301 >> 2] | 0; + if (($302 | 0) != 0) { + $R7_0 = $302; + $RP9_0 = $301; + continue; + } + $305 = $R7_0 + 16 | 0; + $306 = HEAP32[$305 >> 2] | 0; + if (($306 | 0) == 0) { + break; + } else { + $R7_0 = $306; + $RP9_0 = $305; + } + } + if ($RP9_0 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$RP9_0 >> 2] = 0; + $R7_1 = $R7_0; + break; + } + } else { + $278 = HEAP32[$mem + ($10 & -8) >> 2] | 0; + if ($278 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + if ((HEAP32[($278 + 12 | 0) >> 2] | 0) != ($267 | 0)) { + _abort(); + } + if ((HEAP32[($273 + 8 | 0) >> 2] | 0) == ($267 | 0)) { + HEAP32[($278 + 12 | 0) >> 2] = $273; + HEAP32[($273 + 8 | 0) >> 2] = $278; + $R7_1 = $273; + break; + } else { + _abort(); + } + } + } while (0); + if (($270 | 0) == 0) { + break; + } + $320 = 384 + (HEAP32[($mem + (($10 & -8) + 20) | 0) >> 2] << 2) | 0; + do { + if (($267 | 0) == (HEAP32[$320 >> 2] | 0)) { + HEAP32[$320 >> 2] = $R7_1; + if (($R7_1 | 0) != 0) { + break; + } + HEAP32[21] = HEAP32[21] & (1 << HEAP32[($mem + (($10 & -8) + 20) | 0) >> 2] ^ -1); + break L726; + } else { + if ($270 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + if ((HEAP32[($270 + 16 | 0) >> 2] | 0) == ($267 | 0)) { + HEAP32[($270 + 16 | 0) >> 2] = $R7_1; + } else { + HEAP32[$270 + 20 >> 2] = $R7_1; + } + if (($R7_1 | 0) == 0) { + break L726; + } + } + } while (0); + if ($R7_1 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + HEAP32[$R7_1 + 24 >> 2] = $270; + $351 = HEAP32[$mem + (($10 & -8) + 8) >> 2] | 0; + do { + if (($351 | 0) != 0) { + if ($351 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$R7_1 + 16 >> 2] = $351; + HEAP32[$351 + 24 >> 2] = $R7_1; + break; + } + } + } while (0); + $364 = HEAP32[$mem + (($10 & -8) + 12) >> 2] | 0; + if (($364 | 0) == 0) { + break; + } + if ($364 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$R7_1 + 20 >> 2] = $364; + HEAP32[$364 + 24 >> 2] = $R7_1; + break; + } + } + } while (0); + HEAP32[$p_0 + 4 >> 2] = $227 | 1; + HEAP32[$189 + $227 >> 2] = $227; + if (($p_0 | 0) != (HEAP32[25] | 0)) { + $psize_1 = $227; + break; + } + HEAP32[22] = $227; + return; + } else { + HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] = $194 & -2; + HEAP32[$p_0 + 4 >> 2] = $psize_0 | 1; + HEAP32[$189 + $psize_0 >> 2] = $psize_0; + $psize_1 = $psize_0; + } + } while (0); + $390 = $psize_1 >>> 3; + if ($psize_1 >>> 0 < 256) { + $396 = HEAP32[20] | 0; + do { + if (($396 & 1 << $390 | 0) == 0) { + HEAP32[20] = $396 | 1 << $390; + $F16_0 = 120 + ($390 << 1 << 2) | 0; + $_pre_phi = 120 + (($390 << 1) + 2 << 2) | 0; + } else { + $404 = HEAP32[(120 + (($390 << 1) + 2 << 2) | 0) >> 2] | 0; + if ($404 >>> 0 >= (HEAP32[24] | 0) >>> 0) { + $F16_0 = $404; + $_pre_phi = 120 + (($390 << 1) + 2 << 2) | 0; + break; + } + _abort(); + } + } while (0); + HEAP32[$_pre_phi >> 2] = $p_0; + HEAP32[$F16_0 + 12 >> 2] = $p_0; + HEAP32[$p_0 + 8 >> 2] = $F16_0; + HEAP32[$p_0 + 12 >> 2] = 120 + ($390 << 1 << 2) | 0; + return; + } + $414 = $p_0; + $415 = $psize_1 >>> 8; + do { + if (($415 | 0) == 0) { + $I18_0 = 0; + } else { + if ($psize_1 >>> 0 > 16777215) { + $I18_0 = 31; + break; + } + $428 = $415 << (($415 + 1048320 | 0) >>> 16 & 8) << ((($415 << (($415 + 1048320 | 0) >>> 16 & 8)) + 520192 | 0) >>> 16 & 4); + $436 = 14 - ((($415 << (($415 + 1048320 | 0) >>> 16 & 8)) + 520192 | 0) >>> 16 & 4 | ($415 + 1048320 | 0) >>> 16 & 8 | ($428 + 245760 | 0) >>> 16 & 2) + ($428 << (($428 + 245760 | 0) >>> 16 & 2) >>> 15) | 0; + $I18_0 = $psize_1 >>> (($436 + 7 | 0) >>> 0) & 1 | $436 << 1; + } + } while (0); + $443 = 384 + ($I18_0 << 2) | 0; + HEAP32[$p_0 + 28 >> 2] = $I18_0; + HEAP32[$p_0 + 20 >> 2] = 0; + HEAP32[$p_0 + 16 >> 2] = 0; + $447 = HEAP32[21] | 0; + $448 = 1 << $I18_0; + do { + if (($447 & $448 | 0) == 0) { + HEAP32[21] = $447 | $448; + HEAP32[$443 >> 2] = $414; + HEAP32[$p_0 + 24 >> 2] = $443; + HEAP32[$p_0 + 12 >> 2] = $p_0; + HEAP32[$p_0 + 8 >> 2] = $p_0; + } else { + if (($I18_0 | 0) == 31) { + $463 = 0; + } else { + $463 = 25 - ($I18_0 >>> 1) | 0; + } + $K19_0 = $psize_1 << $463; + $T_0 = HEAP32[$443 >> 2] | 0; + while (1) { + if ((HEAP32[$T_0 + 4 >> 2] & -8 | 0) == ($psize_1 | 0)) { + break; + } + $472 = $T_0 + 16 + ($K19_0 >>> 31 << 2) | 0; + $473 = HEAP32[$472 >> 2] | 0; + if (($473 | 0) == 0) { + label = 569; + break; + } else { + $K19_0 = $K19_0 << 1; + $T_0 = $473; + } + } + if ((label | 0) == 569) { + if ($472 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$472 >> 2] = $414; + HEAP32[$p_0 + 24 >> 2] = $T_0; + HEAP32[$p_0 + 12 >> 2] = $p_0; + HEAP32[$p_0 + 8 >> 2] = $p_0; + break; + } + } + $486 = $T_0 + 8 | 0; + $487 = HEAP32[$486 >> 2] | 0; + $489 = HEAP32[24] | 0; + if ($T_0 >>> 0 < $489 >>> 0) { + _abort(); + } + if ($487 >>> 0 < $489 >>> 0) { + _abort(); + } else { + HEAP32[$487 + 12 >> 2] = $414; + HEAP32[$486 >> 2] = $414; + HEAP32[$p_0 + 8 >> 2] = $487; + HEAP32[$p_0 + 12 >> 2] = $T_0; + HEAP32[$p_0 + 24 >> 2] = 0; + break; + } + } + } while (0); + $501 = (HEAP32[28] | 0) - 1 | 0; + HEAP32[28] = $501; + if (($501 | 0) == 0) { + $sp_0_in_i = 536; + } else { + return; + } + while (1) { + $sp_0_i = HEAP32[$sp_0_in_i >> 2] | 0; + if (($sp_0_i | 0) == 0) { + break; + } else { + $sp_0_in_i = $sp_0_i + 8 | 0; + } + } + HEAP32[28] = -1; + STACKTOP = sp; + return; +} + diff --git a/tools/test-js-optimizer-asm-outline.js b/tools/test-js-optimizer-asm-outline.js new file mode 100644 index 00000000..153d7feb --- /dev/null +++ b/tools/test-js-optimizer-asm-outline.js @@ -0,0 +1,606 @@ +function linear() { + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); + cheez(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); +} +function _free($mem) { + $mem = $mem | 0; + var $3 = 0, $4 = 0, $5 = 0, $10 = 0, $11 = 0, $14 = 0, $15 = 0, $16 = 0, $21 = 0, $_sum233 = 0, $24 = 0, $25 = 0, $26 = 0, $32 = 0, $37 = 0, $40 = 0, $43 = 0, $64 = 0, $_pre_phi307 = 0, $69 = 0, $72 = 0, $75 = 0, $80 = 0, $84 = 0, $88 = 0, $94 = 0, $95 = 0, $99 = 0, $100 = 0, $RP_0 = 0, $R_0 = 0, $102 = 0, $103 = 0, $106 = 0, $107 = 0, $R_1 = 0, $118 = 0, $120 = 0, $134 = 0, $151 = 0, $164 = 0, $177 = 0, $psize_0 = 0, $p_0 = 0, $189 = 0, $193 = 0, $194 = 0, $204 = 0, $220 = 0, $227 = 0, $228 = 0, $233 = 0, $236 = 0, $239 = 0, $262 = 0, $_pre_phi305 = 0, $267 = 0, $270 = 0, $273 = 0, $278 = 0, $283 = 0, $287 = 0, $293 = 0, $294 = 0, $298 = 0, $299 = 0, $RP9_0 = 0, $R7_0 = 0, $301 = 0, $302 = 0, $305 = 0, $306 = 0, $R7_1 = 0, $318 = 0, $320 = 0, $334 = 0, $351 = 0, $364 = 0, $psize_1 = 0, $390 = 0, $393 = 0, $395 = 0, $396 = 0, $397 = 0, $403 = 0, $404 = 0, $_pre_phi = 0, $F16_0 = 0, $414 = 0, $415 = 0, $422 = 0, $423 = 0, $426 = 0, $428 = 0, $431 = 0, $436 = 0, $I18_0 = 0, $443 = 0, $447 = 0, $448 = 0, $463 = 0, $T_0 = 0, $K19_0 = 0, $472 = 0, $473 = 0, $486 = 0, $487 = 0, $489 = 0, $501 = 0, $sp_0_in_i = 0, $sp_0_i = 0, label = 0, sp = 0; + sp = STACKTOP; + if (($mem | 0) == 0) { + STACKTOP = sp; + return; + } + $3 = $mem - 8 | 0; + $4 = $3; + $5 = HEAP32[24] | 0; + if ($3 >>> 0 < $5 >>> 0) { + _abort(); + } + $10 = HEAP32[$mem - 4 >> 2] | 0; + $11 = $10 & 3; + if (($11 | 0) == 1) { + _abort(); + } + $14 = $10 & -8; + $15 = $mem + ($14 - 8) | 0; + $16 = $15; + L621 : do { + if (($10 & 1 | 0) == 0) { + $21 = HEAP32[$3 >> 2] | 0; + if (($11 | 0) == 0) { + return; + } + $_sum233 = -8 - $21 | 0; + $24 = $mem + $_sum233 | 0; + $25 = $24; + $26 = $21 + $14 | 0; + if ($24 >>> 0 < $5 >>> 0) { + _abort(); + } + if (($25 | 0) == (HEAP32[25] | 0)) { + $177 = $mem + ($14 - 4) | 0; + if ((HEAP32[$177 >> 2] & 3 | 0) != 3) { + $p_0 = $25; + $psize_0 = $26; + break; + } + HEAP32[22] = $26; + HEAP32[$177 >> 2] = HEAP32[$177 >> 2] & -2; + HEAP32[$mem + ($_sum233 + 4) >> 2] = $26 | 1; + HEAP32[$15 >> 2] = $26; + return; + } + $32 = $21 >>> 3; + if ($21 >>> 0 < 256) { + $37 = HEAP32[$mem + ($_sum233 + 8) >> 2] | 0; + $40 = HEAP32[$mem + ($_sum233 + 12) >> 2] | 0; + $43 = 120 + ($32 << 1 << 2) | 0; + do { + if (($37 | 0) != ($43 | 0)) { + if ($37 >>> 0 < $5 >>> 0) { + _abort(); + } + if ((HEAP32[$37 + 12 >> 2] | 0) == ($25 | 0)) { + break; + } + _abort(); + } + } while (0); + if (($40 | 0) == ($37 | 0)) { + HEAP32[20] = HEAP32[20] & (1 << $32 ^ -1); + $p_0 = $25; + $psize_0 = $26; + break; + } + do { + if (($40 | 0) == ($43 | 0)) { + $_pre_phi307 = $40 + 8 | 0; + } else { + if ($40 >>> 0 < $5 >>> 0) { + _abort(); + } + $64 = $40 + 8 | 0; + if ((HEAP32[$64 >> 2] | 0) == ($25 | 0)) { + $_pre_phi307 = $64; + break; + } + _abort(); + } + } while (0); + HEAP32[$37 + 12 >> 2] = $40; + HEAP32[$_pre_phi307 >> 2] = $37; + $p_0 = $25; + $psize_0 = $26; + break; + } + $69 = $24; + $72 = HEAP32[$mem + ($_sum233 + 24) >> 2] | 0; + $75 = HEAP32[$mem + ($_sum233 + 12) >> 2] | 0; + do { + if (($75 | 0) == ($69 | 0)) { + $94 = $mem + ($_sum233 + 20) | 0; + $95 = HEAP32[$94 >> 2] | 0; + if (($95 | 0) == 0) { + $99 = $mem + ($_sum233 + 16) | 0; + $100 = HEAP32[$99 >> 2] | 0; + if (($100 | 0) == 0) { + $R_1 = 0; + break; + } else { + $R_0 = $100; + $RP_0 = $99; + } + } else { + $R_0 = $95; + $RP_0 = $94; + } + while (1) { + $102 = $R_0 + 20 | 0; + $103 = HEAP32[$102 >> 2] | 0; + if (($103 | 0) != 0) { + $R_0 = $103; + $RP_0 = $102; + continue; + } + $106 = $R_0 + 16 | 0; + $107 = HEAP32[$106 >> 2] | 0; + if (($107 | 0) == 0) { + break; + } else { + $R_0 = $107; + $RP_0 = $106; + } + } + if ($RP_0 >>> 0 < $5 >>> 0) { + _abort(); + } else { + HEAP32[$RP_0 >> 2] = 0; + $R_1 = $R_0; + break; + } + } else { + $80 = HEAP32[$mem + ($_sum233 + 8) >> 2] | 0; + if ($80 >>> 0 < $5 >>> 0) { + _abort(); + } + $84 = $80 + 12 | 0; + if ((HEAP32[$84 >> 2] | 0) != ($69 | 0)) { + _abort(); + } + $88 = $75 + 8 | 0; + if ((HEAP32[$88 >> 2] | 0) == ($69 | 0)) { + HEAP32[$84 >> 2] = $75; + HEAP32[$88 >> 2] = $80; + $R_1 = $75; + break; + } else { + _abort(); + } + } + } while (0); + if (($72 | 0) == 0) { + $p_0 = $25; + $psize_0 = $26; + break; + } + $118 = $mem + ($_sum233 + 28) | 0; + $120 = 384 + (HEAP32[$118 >> 2] << 2) | 0; + do { + if (($69 | 0) == (HEAP32[$120 >> 2] | 0)) { + HEAP32[$120 >> 2] = $R_1; + if (($R_1 | 0) != 0) { + break; + } + HEAP32[21] = HEAP32[21] & (1 << HEAP32[$118 >> 2] ^ -1); + $p_0 = $25; + $psize_0 = $26; + break L621; + } else { + if ($72 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + $134 = $72 + 16 | 0; + if ((HEAP32[$134 >> 2] | 0) == ($69 | 0)) { + HEAP32[$134 >> 2] = $R_1; + } else { + HEAP32[$72 + 20 >> 2] = $R_1; + } + if (($R_1 | 0) == 0) { + $p_0 = $25; + $psize_0 = $26; + break L621; + } + } + } while (0); + if ($R_1 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + HEAP32[$R_1 + 24 >> 2] = $72; + $151 = HEAP32[$mem + ($_sum233 + 16) >> 2] | 0; + do { + if (($151 | 0) != 0) { + if ($151 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$R_1 + 16 >> 2] = $151; + HEAP32[$151 + 24 >> 2] = $R_1; + break; + } + } + } while (0); + $164 = HEAP32[$mem + ($_sum233 + 20) >> 2] | 0; + if (($164 | 0) == 0) { + $p_0 = $25; + $psize_0 = $26; + break; + } + if ($164 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$R_1 + 20 >> 2] = $164; + HEAP32[$164 + 24 >> 2] = $R_1; + $p_0 = $25; + $psize_0 = $26; + break; + } + } else { + $p_0 = $4; + $psize_0 = $14; + } + } while (0); + $189 = $p_0; + if ($189 >>> 0 >= $15 >>> 0) { + _abort(); + } + $193 = $mem + ($14 - 4) | 0; + $194 = HEAP32[$193 >> 2] | 0; + if (($194 & 1 | 0) == 0) { + _abort(); + } + do { + if (($194 & 2 | 0) == 0) { + if (($16 | 0) == (HEAP32[26] | 0)) { + $204 = (HEAP32[23] | 0) + $psize_0 | 0; + HEAP32[23] = $204; + HEAP32[26] = $p_0; + HEAP32[$p_0 + 4 >> 2] = $204 | 1; + if (($p_0 | 0) == (HEAP32[25] | 0)) { + HEAP32[25] = 0; + HEAP32[22] = 0; + } + if ($204 >>> 0 <= (HEAP32[27] | 0) >>> 0) { + return; + } + _sys_trim(0) | 0; + return; + } + if (($16 | 0) == (HEAP32[25] | 0)) { + $220 = (HEAP32[22] | 0) + $psize_0 | 0; + HEAP32[22] = $220; + HEAP32[25] = $p_0; + HEAP32[$p_0 + 4 >> 2] = $220 | 1; + HEAP32[$189 + $220 >> 2] = $220; + return; + } + $227 = ($194 & -8) + $psize_0 | 0; + $228 = $194 >>> 3; + L726 : do { + if ($194 >>> 0 < 256) { + $233 = HEAP32[$mem + $14 >> 2] | 0; + $236 = HEAP32[$mem + ($14 | 4) >> 2] | 0; + $239 = 120 + ($228 << 1 << 2) | 0; + do { + if (($233 | 0) != ($239 | 0)) { + if ($233 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + if ((HEAP32[$233 + 12 >> 2] | 0) == ($16 | 0)) { + break; + } + _abort(); + } + } while (0); + if (($236 | 0) == ($233 | 0)) { + HEAP32[20] = HEAP32[20] & (1 << $228 ^ -1); + break; + } + do { + if (($236 | 0) == ($239 | 0)) { + $_pre_phi305 = $236 + 8 | 0; + } else { + if ($236 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + $262 = $236 + 8 | 0; + if ((HEAP32[$262 >> 2] | 0) == ($16 | 0)) { + $_pre_phi305 = $262; + break; + } + _abort(); + } + } while (0); + HEAP32[$233 + 12 >> 2] = $236; + HEAP32[$_pre_phi305 >> 2] = $233; + } else { + $267 = $15; + $270 = HEAP32[$mem + ($14 + 16) >> 2] | 0; + $273 = HEAP32[$mem + ($14 | 4) >> 2] | 0; + do { + if (($273 | 0) == ($267 | 0)) { + $293 = $mem + ($14 + 12) | 0; + $294 = HEAP32[$293 >> 2] | 0; + if (($294 | 0) == 0) { + $298 = $mem + ($14 + 8) | 0; + $299 = HEAP32[$298 >> 2] | 0; + if (($299 | 0) == 0) { + $R7_1 = 0; + break; + } else { + $R7_0 = $299; + $RP9_0 = $298; + } + } else { + $R7_0 = $294; + $RP9_0 = $293; + } + while (1) { + $301 = $R7_0 + 20 | 0; + $302 = HEAP32[$301 >> 2] | 0; + if (($302 | 0) != 0) { + $R7_0 = $302; + $RP9_0 = $301; + continue; + } + $305 = $R7_0 + 16 | 0; + $306 = HEAP32[$305 >> 2] | 0; + if (($306 | 0) == 0) { + break; + } else { + $R7_0 = $306; + $RP9_0 = $305; + } + } + if ($RP9_0 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$RP9_0 >> 2] = 0; + $R7_1 = $R7_0; + break; + } + } else { + $278 = HEAP32[$mem + $14 >> 2] | 0; + if ($278 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + $283 = $278 + 12 | 0; + if ((HEAP32[$283 >> 2] | 0) != ($267 | 0)) { + _abort(); + } + $287 = $273 + 8 | 0; + if ((HEAP32[$287 >> 2] | 0) == ($267 | 0)) { + HEAP32[$283 >> 2] = $273; + HEAP32[$287 >> 2] = $278; + $R7_1 = $273; + break; + } else { + _abort(); + } + } + } while (0); + if (($270 | 0) == 0) { + break; + } + $318 = $mem + ($14 + 20) | 0; + $320 = 384 + (HEAP32[$318 >> 2] << 2) | 0; + do { + if (($267 | 0) == (HEAP32[$320 >> 2] | 0)) { + HEAP32[$320 >> 2] = $R7_1; + if (($R7_1 | 0) != 0) { + break; + } + HEAP32[21] = HEAP32[21] & (1 << HEAP32[$318 >> 2] ^ -1); + break L726; + } else { + if ($270 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + $334 = $270 + 16 | 0; + if ((HEAP32[$334 >> 2] | 0) == ($267 | 0)) { + HEAP32[$334 >> 2] = $R7_1; + } else { + HEAP32[$270 + 20 >> 2] = $R7_1; + } + if (($R7_1 | 0) == 0) { + break L726; + } + } + } while (0); + if ($R7_1 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + HEAP32[$R7_1 + 24 >> 2] = $270; + $351 = HEAP32[$mem + ($14 + 8) >> 2] | 0; + do { + if (($351 | 0) != 0) { + if ($351 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$R7_1 + 16 >> 2] = $351; + HEAP32[$351 + 24 >> 2] = $R7_1; + break; + } + } + } while (0); + $364 = HEAP32[$mem + ($14 + 12) >> 2] | 0; + if (($364 | 0) == 0) { + break; + } + if ($364 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$R7_1 + 20 >> 2] = $364; + HEAP32[$364 + 24 >> 2] = $R7_1; + break; + } + } + } while (0); + HEAP32[$p_0 + 4 >> 2] = $227 | 1; + HEAP32[$189 + $227 >> 2] = $227; + if (($p_0 | 0) != (HEAP32[25] | 0)) { + $psize_1 = $227; + break; + } + HEAP32[22] = $227; + return; + } else { + HEAP32[$193 >> 2] = $194 & -2; + HEAP32[$p_0 + 4 >> 2] = $psize_0 | 1; + HEAP32[$189 + $psize_0 >> 2] = $psize_0; + $psize_1 = $psize_0; + } + } while (0); + $390 = $psize_1 >>> 3; + if ($psize_1 >>> 0 < 256) { + $393 = $390 << 1; + $395 = 120 + ($393 << 2) | 0; + $396 = HEAP32[20] | 0; + $397 = 1 << $390; + do { + if (($396 & $397 | 0) == 0) { + HEAP32[20] = $396 | $397; + $F16_0 = $395; + $_pre_phi = 120 + ($393 + 2 << 2) | 0; + } else { + $403 = 120 + ($393 + 2 << 2) | 0; + $404 = HEAP32[$403 >> 2] | 0; + if ($404 >>> 0 >= (HEAP32[24] | 0) >>> 0) { + $F16_0 = $404; + $_pre_phi = $403; + break; + } + _abort(); + } + } while (0); + HEAP32[$_pre_phi >> 2] = $p_0; + HEAP32[$F16_0 + 12 >> 2] = $p_0; + HEAP32[$p_0 + 8 >> 2] = $F16_0; + HEAP32[$p_0 + 12 >> 2] = $395; + return; + } + $414 = $p_0; + $415 = $psize_1 >>> 8; + do { + if (($415 | 0) == 0) { + $I18_0 = 0; + } else { + if ($psize_1 >>> 0 > 16777215) { + $I18_0 = 31; + break; + } + $422 = ($415 + 1048320 | 0) >>> 16 & 8; + $423 = $415 << $422; + $426 = ($423 + 520192 | 0) >>> 16 & 4; + $428 = $423 << $426; + $431 = ($428 + 245760 | 0) >>> 16 & 2; + $436 = 14 - ($426 | $422 | $431) + ($428 << $431 >>> 15) | 0; + $I18_0 = $psize_1 >>> (($436 + 7 | 0) >>> 0) & 1 | $436 << 1; + } + } while (0); + $443 = 384 + ($I18_0 << 2) | 0; + HEAP32[$p_0 + 28 >> 2] = $I18_0; + HEAP32[$p_0 + 20 >> 2] = 0; + HEAP32[$p_0 + 16 >> 2] = 0; + $447 = HEAP32[21] | 0; + $448 = 1 << $I18_0; + do { + if (($447 & $448 | 0) == 0) { + HEAP32[21] = $447 | $448; + HEAP32[$443 >> 2] = $414; + HEAP32[$p_0 + 24 >> 2] = $443; + HEAP32[$p_0 + 12 >> 2] = $p_0; + HEAP32[$p_0 + 8 >> 2] = $p_0; + } else { + if (($I18_0 | 0) == 31) { + $463 = 0; + } else { + $463 = 25 - ($I18_0 >>> 1) | 0; + } + $K19_0 = $psize_1 << $463; + $T_0 = HEAP32[$443 >> 2] | 0; + while (1) { + if ((HEAP32[$T_0 + 4 >> 2] & -8 | 0) == ($psize_1 | 0)) { + break; + } + $472 = $T_0 + 16 + ($K19_0 >>> 31 << 2) | 0; + $473 = HEAP32[$472 >> 2] | 0; + if (($473 | 0) == 0) { + label = 569; + break; + } else { + $K19_0 = $K19_0 << 1; + $T_0 = $473; + } + } + if ((label | 0) == 569) { + if ($472 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$472 >> 2] = $414; + HEAP32[$p_0 + 24 >> 2] = $T_0; + HEAP32[$p_0 + 12 >> 2] = $p_0; + HEAP32[$p_0 + 8 >> 2] = $p_0; + break; + } + } + $486 = $T_0 + 8 | 0; + $487 = HEAP32[$486 >> 2] | 0; + $489 = HEAP32[24] | 0; + if ($T_0 >>> 0 < $489 >>> 0) { + _abort(); + } + if ($487 >>> 0 < $489 >>> 0) { + _abort(); + } else { + HEAP32[$487 + 12 >> 2] = $414; + HEAP32[$486 >> 2] = $414; + HEAP32[$p_0 + 8 >> 2] = $487; + HEAP32[$p_0 + 12 >> 2] = $T_0; + HEAP32[$p_0 + 24 >> 2] = 0; + break; + } + } + } while (0); + $501 = (HEAP32[28] | 0) - 1 | 0; + HEAP32[28] = $501; + if (($501 | 0) == 0) { + $sp_0_in_i = 536; + } else { + return; + } + while (1) { + $sp_0_i = HEAP32[$sp_0_in_i >> 2] | 0; + if (($sp_0_i | 0) == 0) { + break; + } else { + $sp_0_in_i = $sp_0_i + 8 | 0; + } + } + HEAP32[28] = -1; + STACKTOP = sp; + return; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS +// EXTRA_INFO: { "sizeToOutline": 1000 } diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index 59a42010..b7afab26 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -63,6 +63,9 @@ function b($this, $__n) { HEAP32[($this + 4 & 16777215) >> 2] = $40; } HEAP8[$38 + $40 & 16777215] = 0; + HEAP32[$4] = ~HEAP32[$5]; + HEAP32[$4] = ~HEAP32[$5]; + HEAP32[$4] = ~HEAP32[$5]; return; } function rett() { @@ -127,6 +130,7 @@ function compare_result_simplification() { HEAP32[$4] = HEAP32[$5] == HEAP32[$6]; HEAP32[$4] = HEAP32[$5] === HEAP32[$6]; HEAP32[$4] = HEAP32[$5] != HEAP32[$6]; + HEAP32[$4] = HEAP32[$5] !== HEAP32[$6]; var x = HEAP32[$5] != HEAP32[$6] | 0; } function tempDoublePtr($45, $14, $28, $42) { diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js index 7ca941fa..b762a60e 100644 --- a/tools/test-js-optimizer-asm-pre.js +++ b/tools/test-js-optimizer-asm-pre.js @@ -64,6 +64,12 @@ function b($this, $__n) { HEAP32[(($this + 4 | 0) & 16777215) >> 2] = $40; } HEAP8[($38 + $40 | 0) & 16777215] = 0; + // Eliminate the |0. + HEAP32[$4] = ((~(HEAP32[$5]|0))|0); + // Rewrite to ~. + HEAP32[$4] = HEAP32[$5]^-1; + // Rewrite to ~ and eliminate the |0. + HEAP32[$4] = ((HEAP32[$5]|0)^-1)|0; return; } function rett() { @@ -131,6 +137,7 @@ function compare_result_simplification() { HEAP32[$4] = (HEAP32[$5] == HEAP32[$6]) & 1; HEAP32[$4] = (HEAP32[$5] === HEAP32[$6]) & 1; HEAP32[$4] = (HEAP32[$5] != HEAP32[$6]) & 1; + HEAP32[$4] = (HEAP32[$5] !== HEAP32[$6]) & 1; // Convert the &1 to |0 here, since we don't get an implicit coersion. var x = (HEAP32[$5] != HEAP32[$6]) & 1; } |