summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemcc8
-rwxr-xr-xemscripten.py4
-rw-r--r--src/parseTools.js34
-rw-r--r--src/preamble.js33
-rw-r--r--src/relooper/Relooper.cpp27
-rw-r--r--src/relooper/Relooper.h4
-rw-r--r--src/relooper/test.txt4
-rw-r--r--src/runtime.js2
-rw-r--r--tests/test_core.py2
-rw-r--r--tests/test_other.py2
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js506
-rw-r--r--tools/eliminator/asm-eliminator-test.js651
-rw-r--r--tools/js-optimizer.js309
-rw-r--r--tools/js_optimizer.py6
-rw-r--r--tools/shared.py2
15 files changed, 1466 insertions, 128 deletions
diff --git a/emcc b/emcc
index f425ff4d..4be24e20 100755
--- a/emcc
+++ b/emcc
@@ -1196,7 +1196,6 @@ try:
shared.Settings.ASM_JS = 1
assert shared.Settings.ALLOW_MEMORY_GROWTH == 0, 'memory growth not supported in fastcomp yet'
assert shared.Settings.UNALIGNED_MEMORY == 0, 'forced unaligned memory not supported in fastcomp'
- assert shared.Settings.SAFE_HEAP == 0, 'safe heap not supported in fastcomp yet'
assert shared.Settings.CHECK_HEAP_ALIGN == 0, 'check heap align not supported in fastcomp yet'
assert shared.Settings.SAFE_DYNCALLS == 0, 'safe dyncalls not supported in fastcomp'
assert shared.Settings.RESERVED_FUNCTION_POINTERS == 0, 'reserved function pointers not supported in fastcomp'
@@ -1230,6 +1229,9 @@ try:
shared.Settings.CORRECT_OVERFLOWS = 1
assert not shared.Settings.PGO, 'cannot run PGO in ASM_JS mode'
+ if shared.Settings.SAFE_HEAP and not js_opts:
+ logging.warning('asm.js+SAFE_HEAP requires js opts to be run (-O1 or above by default)')
+
if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2:
debug_level = 4 # must keep debug info to do line-by-line operations
@@ -1991,6 +1993,8 @@ try:
if DEBUG: save_intermediate('closure')
if js_opts:
+ if shared.Settings.ASM_JS and shared.Settings.SAFE_HEAP: js_optimizer_queue += ['safeHeap']
+
if shared.Settings.OUTLINING_LIMIT > 0 and shared.Settings.ASM_JS:
js_optimizer_queue += ['outline']
js_optimizer_extra_info['sizeToOutline'] = shared.Settings.OUTLINING_LIMIT
@@ -1999,7 +2003,7 @@ try:
js_optimizer_queue += ['registerize']
if opt_level > 0:
- if debug_level < 2 and shared.Settings.ASM_JS: js_optimizer_queue = map(lambda p: p if p != 'registerize' else 'registerizeAndMinify', js_optimizer_queue)
+ if debug_level < 2 and shared.Settings.ASM_JS: js_optimizer_queue += ['minifyNames']
if debug_level == 0: js_optimizer_queue += ['minifyWhitespace']
if closure and shared.Settings.ASM_JS:
diff --git a/emscripten.py b/emscripten.py
index befad8d5..aeace63d 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -455,7 +455,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in math_envs]
if settings['RESERVED_FUNCTION_POINTERS'] > 0: basic_funcs.append('jsCall')
- if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE', 'SAFE_HEAP_CLEAR']
+ if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE']
if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
if settings['ASSERTIONS']:
basic_funcs += ['nullFunc']
@@ -956,7 +956,7 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in math_envs]
if settings['RESERVED_FUNCTION_POINTERS'] > 0: basic_funcs.append('jsCall')
- if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE', 'SAFE_HEAP_CLEAR']
+ if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE']
if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
if settings['ASSERTIONS']:
basic_funcs += ['nullFunc']
diff --git a/src/parseTools.js b/src/parseTools.js
index be0cbcab..036ccfc1 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1327,18 +1327,22 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa
var printType = type;
if (printType !== 'null' && printType[0] !== '#') printType = '"' + safeQuote(printType) + '"';
if (printType[0] === '#') printType = printType.substr(1);
- return asmCoercion('SAFE_HEAP_LOAD(' + asmCoercion(offset, 'i32') + ', ' + (ASM_JS ? 0 : printType) + ', ' + (!!unsigned+0) + ', ' + ((!checkSafeHeap() || ignore)|0) + ')', type);
- } else {
- var ret = makeGetSlabs(ptr, type, false, unsigned)[0] + '[' + getHeapOffset(offset, type, forceAsm) + ']';
- if (ASM_JS && (phase == 'funcs' || forceAsm)) {
- ret = asmCoercion(ret, type);
- }
- if (ASM_HEAP_LOG) {
- ret = makeInlineCalculation('(asmPrint' + (type in Runtime.FLOAT_TYPES ? 'Float' : 'Int') + '(' + (asmPrintCounter++) + ',' + asmCoercion('VALUE', type) + '), VALUE)', ret,
- 'temp' + (type in Runtime.FLOAT_TYPES ? 'Double' : 'Int'));
+ if (ASM_JS) {
+ if (!ignore) return asmCoercion('SAFE_HEAP_LOAD(' + asmCoercion(offset, 'i32') + ', ' + Runtime.getNativeTypeSize(type) + ', ' + ((type in Runtime.FLOAT_TYPES)|0) + ')', type);
+ // else fall through
+ } else {
+ return asmCoercion('SAFE_HEAP_LOAD(' + offset + ', ' + (ASM_JS ? 0 : printType) + ', ' + (!!unsigned+0) + ', ' + ((!checkSafeHeap() || ignore)|0) + ')', type);
}
- return ret;
}
+ var ret = makeGetSlabs(ptr, type, false, unsigned)[0] + '[' + getHeapOffset(offset, type, forceAsm) + ']';
+ if (ASM_JS && (phase == 'funcs' || forceAsm)) {
+ ret = asmCoercion(ret, type);
+ }
+ if (ASM_HEAP_LOG) {
+ ret = makeInlineCalculation('(asmPrint' + (type in Runtime.FLOAT_TYPES ? 'Float' : 'Int') + '(' + (asmPrintCounter++) + ',' + asmCoercion('VALUE', type) + '), VALUE)', ret,
+ 'temp' + (type in Runtime.FLOAT_TYPES ? 'Double' : 'Int'));
+ }
+ return ret;
}
function makeGetValueAsm(ptr, pos, type, unsigned) {
@@ -1435,10 +1439,14 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
var printType = type;
if (printType !== 'null' && printType[0] !== '#') printType = '"' + safeQuote(printType) + '"';
if (printType[0] === '#') printType = printType.substr(1);
- return 'SAFE_HEAP_STORE(' + asmCoercion(offset, 'i32') + ', ' + asmCoercion(value, type) + ', ' + (ASM_JS ? 0 : printType) + ', ' + ((!checkSafeHeap() || ignore)|0) + ')';
- } else {
- return makeGetSlabs(ptr, type, true).map(function(slab) { return slab + '[' + getHeapOffset(offset, type, forceAsm) + ']=' + value }).join(sep);
+ if (ASM_JS) {
+ if (!ignore) return asmCoercion('SAFE_HEAP_STORE(' + asmCoercion(offset, 'i32') + ', ' + asmCoercion(value, type) + ', ' + Runtime.getNativeTypeSize(type) + ', ' + ((type in Runtime.FLOAT_TYPES)|0) + ')', type);
+ // else fall through
+ } else {
+ return 'SAFE_HEAP_STORE(' + offset + ', ' + value + ', ' + (ASM_JS ? 0 : printType) + ', ' + ((!checkSafeHeap() || ignore)|0) + ')';
+ }
}
+ return makeGetSlabs(ptr, type, true).map(function(slab) { return slab + '[' + getHeapOffset(offset, type, forceAsm) + ']=' + value }).join(sep);
}
function makeSetValueAsm(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, sep, forcedAlign) {
diff --git a/src/preamble.js b/src/preamble.js
index ac6ee7b3..d70ef4b1 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -21,6 +21,7 @@ Module.print = Module.printErr = function(){};
#endif
#if SAFE_HEAP
+#if ASM_JS == 0
//========================================
// Debugging tools - Heap
//========================================
@@ -166,6 +167,38 @@ function SAFE_HEAP_FILL_HISTORY(from, to, type) {
}
//==========================================
+#else
+// ASM_JS safe heap
+
+function getSafeHeapType(bytes, isFloat) {
+ switch (bytes) {
+ case 1: return 'i8';
+ case 2: return 'i16';
+ case 4: return isFloat ? 'float' : 'i32';
+ case 8: return 'double';
+ default: assert(0);
+ }
+}
+
+function SAFE_HEAP_STORE(dest, value, bytes, isFloat) {
+#if SAFE_HEAP_LOG
+ Module.print('SAFE_HEAP store: ' + [dest, value, bytes, isFloat]);
+#endif
+ assert(dest > 0, 'segmentation fault');
+ assert(dest % bytes === 0);
+ setValue(dest, value, getSafeHeapType(bytes, isFloat), 1);
+}
+
+function SAFE_HEAP_LOAD(dest, bytes, isFloat) {
+#if SAFE_HEAP_LOG
+ Module.print('SAFE_HEAP load: ' + [dest, bytes, isFloat]);
+#endif
+ assert(dest > 0, 'segmentation fault');
+ assert(dest % bytes === 0);
+ return getValue(dest, getSafeHeapType(bytes, isFloat), 1);
+}
+
+#endif
#endif
#if CHECK_HEAP_ALIGN
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index d5772c62..204986da 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -322,12 +322,26 @@ void MultipleShape::RenderLoopPostfix() {
void MultipleShape::Render(bool InLoop) {
RenderLoopPrefix();
- bool First = true;
+
+ // We know that blocks with the same Id were split from the same source, so their contents are identical and they are logically the same, so re-merge them here
+ typedef std::map<int, Shape*> IdShapeMap;
+ IdShapeMap IdMap;
for (BlockShapeMap::iterator iter = InnerMap.begin(); iter != InnerMap.end(); iter++) {
+ int Id = iter->first->Id;
+ IdShapeMap::iterator Test = IdMap.find(Id);
+ if (Test != IdMap.end()) {
+ assert(Shape::IsSimple(iter->second) && Shape::IsSimple(Test->second)); // we can only merge simple blocks, something horrible has gone wrong if we see anything else
+ continue;
+ }
+ IdMap[iter->first->Id] = iter->second;
+ }
+
+ bool First = true;
+ for (IdShapeMap::iterator iter = IdMap.begin(); iter != IdMap.end(); iter++) {
if (AsmJS) {
- PrintIndented("%sif ((label|0) == %d) {\n", First ? "" : "else ", iter->first->Id);
+ PrintIndented("%sif ((label|0) == %d) {\n", First ? "" : "else ", iter->first);
} else {
- PrintIndented("%sif (label == %d) {\n", First ? "" : "else ", iter->first->Id);
+ PrintIndented("%sif (label == %d) {\n", First ? "" : "else ", iter->first);
}
First = false;
Indenter::Indent();
@@ -391,8 +405,8 @@ Relooper::~Relooper() {
for (unsigned i = 0; i < Shapes.size(); i++) delete Shapes[i];
}
-void Relooper::AddBlock(Block *New) {
- New->Id = BlockIdCounter++;
+void Relooper::AddBlock(Block *New, int Id) {
+ New->Id = Id == -1 ? BlockIdCounter++ : Id;
Blocks.push_back(New);
}
@@ -446,8 +460,7 @@ void Relooper::Calculate(Block *Entry) {
for (BlockSet::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) {
Block *Prior = *iter;
Block *Split = new Block(Original->Code, Original->BranchVar);
- Parent->AddBlock(Split);
- PrintDebug(" to %d\n", Split->Id);
+ Parent->AddBlock(Split, Original->Id);
Split->BranchesIn.insert(Prior);
Branch *Details = Prior->BranchesOut[Original];
Prior->BranchesOut[Split] = new Branch(Details->Condition, Details->Code);
diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h
index 6b9394db..85adf359 100644
--- a/src/relooper/Relooper.h
+++ b/src/relooper/Relooper.h
@@ -57,7 +57,7 @@ struct Block {
BlockBranchMap ProcessedBranchesOut;
BlockSet ProcessedBranchesIn;
Shape *Parent; // The shape we are directly inside
- int Id; // A unique identifier, defined when added to relooper
+ int Id; // A unique identifier, defined when added to relooper. Note that this uniquely identifies a *logical* block - if we split it, the two instances have the same content *and* the same Id
const char *Code; // The string representation of the code in this block. Owning pointer (we copy the input)
const char *BranchVar; // If we have more than one branch out, the variable whose value determines where we go
bool IsCheckedMultipleEntry; // If true, we are a multiple entry, so reaching us requires setting the label variable
@@ -191,7 +191,7 @@ struct Relooper {
Relooper();
~Relooper();
- void AddBlock(Block *New);
+ void AddBlock(Block *New, int Id=-1);
// Calculates the shapes
void Calculate(Block *Entry);
diff --git a/src/relooper/test.txt b/src/relooper/test.txt
index cb02b867..82b02ad7 100644
--- a/src/relooper/test.txt
+++ b/src/relooper/test.txt
@@ -91,7 +91,7 @@
}
default: {
var $x_1 = $x_0;
- label = 8;
+ label = 7;
break L1;
}
}
@@ -106,7 +106,7 @@
}
}
}
- if (label == 8) {
+ if (label == 7) {
// code 7
}
// code 4
diff --git a/src/runtime.js b/src/runtime.js
index cd3afb4b..1fc9e026 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -49,7 +49,7 @@ var RuntimeGenerator = {
stackExit: function(initial, force) {
if (initial === 0 && SKIP_STACK_IN_SMALL && !force) return '';
var ret = '';
- if (SAFE_HEAP) {
+ if (SAFE_HEAP && !ASM_JS) {
ret += 'var i = sp; while ((i|0) < (STACKTOP|0)) { SAFE_HEAP_CLEAR(i|0); i = (i+1)|0 }';
}
return ret += 'STACKTOP=sp';
diff --git a/tests/test_core.py b/tests/test_core.py
index 458e04fb..ce778209 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -1486,7 +1486,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
def test_segfault(self):
if self.emcc_args is None: return self.skip('SAFE_HEAP without ta2 means we check types too, which hide segfaults')
- if Settings.ASM_JS: return self.skip('asm does not support safe heap')
+ if os.environ.get('EMCC_FAST_COMPILER') == '1' and '-O2' not in self.emcc_args: return self.skip('todo in non-jsopts-enabled fastcomp')
Settings.SAFE_HEAP = 1
diff --git a/tests/test_other.py b/tests/test_other.py
index 00c42418..5e5dd7a6 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -1721,7 +1721,7 @@ f.close()
(path_from_root('tools', 'test-js-optimizer-asm-regs.js'), open(path_from_root('tools', 'test-js-optimizer-asm-regs-output.js')).read(),
['asm', 'registerize']),
(path_from_root('tools', 'test-js-optimizer-asm-regs-min.js'), open(path_from_root('tools', 'test-js-optimizer-asm-regs-min-output.js')).read(),
- ['asm', 'registerize']),
+ ['asm', 'registerize', 'minifyLocals']),
(path_from_root('tools', 'test-js-optimizer-asm-pre.js'), open(path_from_root('tools', 'test-js-optimizer-asm-pre-output.js')).read(),
['asm', 'simplifyExpressions']),
(path_from_root('tools', 'test-js-optimizer-asm-last.js'), open(path_from_root('tools', 'test-js-optimizer-asm-last-output.js')).read(),
diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js
index a344fc35..7a8baef2 100644
--- a/tools/eliminator/asm-eliminator-test-output.js
+++ b/tools/eliminator/asm-eliminator-test-output.js
@@ -304,4 +304,510 @@ function binary(x) {
memset(f(x)) | 0;
+dmemset(f(x));
}
+function cute($this, $outImage) {
+ $this = $this | 0;
+ $outImage = $outImage | 0;
+ var $retval = 0, $outImage_addr = 0, $width = 0, $height = 0, $bit_depth = 0, $color_type = 0, $data = 0, $bpl = 0, $y = 0, $i = 0, $y76 = 0, $p = 0, $end = 0, $this1 = 0, $call = 0, $call7 = 0, $call8 = 0, $3 = 0, $call17 = 0, $10 = 0, $call32 = 0, $call33 = 0, $17$0 = 0, $call34 = 0, $add_ptr = 0, $32 = 0, $call42 = 0, $35 = 0, $call45 = 0, $41 = 0, $call51 = 0, $43 = 0, $call55 = 0, $call57 = 0, $49 = 0, $call72 = 0, $call75 = 0, label = 0, setjmpLabel = 0, setjmpTable = 0, sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 1;
+ setjmpLabel = 0;
+ setjmpTable = STACKTOP;
+ STACKTOP = STACKTOP + 168 | 0;
+ HEAP32[setjmpTable >> 2] = 0;
+ while (1) switch (label | 0) {
+ case 1:
+ $width = sp | 0;
+ $height = sp + 8 | 0;
+ $bit_depth = sp + 16 | 0;
+ $color_type = sp + 24 | 0;
+ $outImage_addr = $outImage;
+ $this1 = $this;
+ if ((HEAP32[($this1 + 32 | 0) >> 2] | 0 | 0) == 3) {
+ label = 2;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 2:
+ $retval = 0;
+ label = 37;
+ break;
+ case 3:
+ if ((HEAP32[($this1 + 32 | 0) >> 2] | 0 | 0) == 0) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $call = invoke_ii(900, $this1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ($call) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP32[($this1 + 32 | 0) >> 2] = 3;
+ $retval = 0;
+ label = 37;
+ break;
+ case 6:
+ HEAP32[($this1 + 28 | 0) >> 2] = 0;
+ $call7 = invoke_iiii(30, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, 2638 | 0, 156 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $call8 = _saveSetjmp($call7 | 0 | 0, label, setjmpTable) | 0;
+ label = 38;
+ break;
+ case 38:
+ if (($call8 | 0) != 0) {
+ label = 7;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 7:
+ invoke_viii(640, $this1 + 16 | 0 | 0, $this1 + 20 | 0 | 0, $this1 + 24 | 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $3 = HEAP32[($this1 + 28 | 0) >> 2] | 0;
+ if (($3 | 0) == 0) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ invoke_vi(926, $3 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 9;
+ break;
+ case 9:
+ HEAP32[($this1 + 16 | 0) >> 2] = 0;
+ HEAP32[($this1 + 32 | 0) >> 2] = 3;
+ $retval = 0;
+ label = 37;
+ break;
+ case 10:
+ invoke_viiif(2, $outImage_addr | 0, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 20 | 0) >> 2] | 0 | 0, +(+HEAPF32[($this1 | 0) >> 2]));
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $call17 = invoke_ii(832, $outImage_addr | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ($call17) {
+ label = 11;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 11:
+ invoke_viii(640, $this1 + 16 | 0 | 0, $this1 + 20 | 0 | 0, $this1 + 24 | 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $10 = HEAP32[($this1 + 28 | 0) >> 2] | 0;
+ if (($10 | 0) == 0) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ invoke_vi(926, $10 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 13;
+ break;
+ case 13:
+ HEAP32[($this1 + 16 | 0) >> 2] = 0;
+ HEAP32[($this1 + 32 | 0) >> 2] = 3;
+ $retval = 0;
+ label = 37;
+ break;
+ case 14:
+ invoke_iiiiiiiiii(2, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 20 | 0) >> 2] | 0 | 0, $width | 0, $height | 0, $bit_depth | 0, $color_type | 0, 0 | 0, 0 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $call32 = invoke_ii(850, $outImage_addr | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $data = $call32;
+ $call33 = invoke_ii(284, $outImage_addr | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $bpl = $call33;
+ $17$0 = invoke_iii(860, HEAP32[$height >> 2] | 0 | 0, 4 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $call34 = invoke_ii(550, (tempRet0 ? -1 : $17$0) | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ HEAP32[($this1 + 28 | 0) >> 2] = $call34;
+ $y = 0;
+ label = 15;
+ break;
+ case 15:
+ if ($y >>> 0 < (HEAP32[$height >> 2] | 0) >>> 0) {
+ label = 16;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 16:
+ $add_ptr = $data + (Math_imul($y, $bpl) | 0) | 0;
+ HEAP32[((HEAP32[($this1 + 28 | 0) >> 2] | 0) + ($y << 2) | 0) >> 2] = $add_ptr;
+ label = 17;
+ break;
+ case 17:
+ $y = $y + 1 | 0;
+ label = 15;
+ break;
+ case 18:
+ invoke_vii(858, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 28 | 0) >> 2] | 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $32 = $outImage_addr;
+ $call42 = invoke_iii(690, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 20 | 0) >> 2] | 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ invoke_vii(1890, $32 | 0, $call42 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $35 = $outImage_addr;
+ $call45 = invoke_iii(256, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 20 | 0) >> 2] | 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ invoke_vii(2126, $35 | 0, $call45 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ HEAP32[($this1 + 32 | 0) >> 2] = 2;
+ invoke_vii(36, HEAP32[($this1 + 16 | 0) >> 2] | 0 | 0, HEAP32[($this1 + 24 | 0) >> 2] | 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ invoke_vii(2752, $this1 | 0, HEAP32[($this1 + 24 | 0) >> 2] | 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $i = 0;
+ label = 19;
+ break;
+ case 19:
+ $41 = $i;
+ $call51 = invoke_ii(618, $this1 + 12 | 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if (($41 | 0) < ($call51 - 1 | 0 | 0)) {
+ label = 20;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 20:
+ $43 = $outImage_addr;
+ $call55 = invoke_iii(502, $this1 + 12 | 0 | 0, $i | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $call57 = invoke_iii(502, $this1 + 12 | 0 | 0, $i + 1 | 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ invoke_viii(550, $43 | 0, $call55 | 0, $call57 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 21;
+ break;
+ case 21:
+ $i = $i + 2 | 0;
+ label = 19;
+ break;
+ case 22:
+ invoke_viii(640, $this1 + 16 | 0 | 0, $this1 + 20 | 0 | 0, $this1 + 24 | 0 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $49 = HEAP32[($this1 + 28 | 0) >> 2] | 0;
+ if (($49 | 0) == 0) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ invoke_vi(926, $49 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 24;
+ break;
+ case 24:
+ HEAP32[($this1 + 16 | 0) >> 2] = 0;
+ HEAP32[($this1 + 32 | 0) >> 2] = 0;
+ if ((HEAP32[$color_type >> 2] | 0 | 0) == 3) {
+ label = 25;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 25:
+ $call72 = invoke_ii(926, $outImage_addr | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if (($call72 | 0) == 3) {
+ label = 26;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 26:
+ $call75 = invoke_ii(860, $outImage_addr | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $y76 = 0;
+ label = 27;
+ break;
+ case 27:
+ if (($y76 | 0) < (HEAP32[$height >> 2] | 0 | 0)) {
+ label = 28;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 28:
+ $p = $data + (Math_imul($y76, $bpl) | 0) | 0;
+ $end = $p + (HEAP32[$width >> 2] | 0) | 0;
+ label = 29;
+ break;
+ case 29:
+ if ($p >>> 0 < $end >>> 0) {
+ label = 30;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 30:
+ if (((HEAP8[$p] | 0) & 255 | 0) >= ($call75 | 0)) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ HEAP8[$p] = 0;
+ label = 32;
+ break;
+ case 32:
+ $p = $p + 1 | 0;
+ label = 29;
+ break;
+ case 33:
+ label = 34;
+ break;
+ case 34:
+ $y76 = $y76 + 1 | 0;
+ label = 27;
+ break;
+ case 35:
+ label = 36;
+ break;
+ case 36:
+ $retval = 1;
+ label = 37;
+ break;
+ case 37:
+ STACKTOP = sp;
+ return $retval | 0;
+ case -1:
+ if ((setjmpLabel | 0) == 6) {
+ $call8 = threwValue;
+ label = 38;
+ }
+ __THREW__ = threwValue = 0;
+ break;
+ }
+ return 0;
+}
diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js
index 4b45e4d4..ad1ed05e 100644
--- a/tools/eliminator/asm-eliminator-test.js
+++ b/tools/eliminator/asm-eliminator-test.js
@@ -378,5 +378,654 @@ function binary(x) {
z = f(x);
+dmemset(z);
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "looop8", "multiloop", "multiloop2", "tempDouble2", "watIf", "select2", "binary"]
+function cute($this, $outImage) {
+ $this = $this | 0;
+ $outImage = $outImage | 0;
+ var $retval = 0, $this_addr = 0, $outImage_addr = 0, $width = 0, $height = 0, $bit_depth = 0, $color_type = 0, $data = 0, $bpl = 0, $y = 0, $i = 0, $color_table_size = 0, $y76 = 0, $p = 0, $end = 0, $this1 = 0, $state = 0, $0 = 0, $cmp = 0, $state2 = 0;
+ var $1 = 0, $cmp3 = 0, $call = 0, $state5 = 0, $row_pointers = 0, $png_ptr = 0, $2 = 0, $call7 = 0, $arraydecay = 0, $call8 = 0, $tobool = 0, $png_ptr10 = 0, $info_ptr = 0, $end_info = 0, $row_pointers11 = 0, $3 = 0, $isnull = 0, $4 = 0, $png_ptr12 = 0, $state13 = 0;
+ var $5 = 0, $png_ptr15 = 0, $6 = 0, $info_ptr16 = 0, $7 = 0, $gamma = 0, $8 = +0, $9 = 0, $call17 = 0, $png_ptr19 = 0, $info_ptr20 = 0, $end_info21 = 0, $row_pointers22 = 0, $10 = 0, $isnull23 = 0, $11 = 0, $png_ptr26 = 0, $state27 = 0, $png_ptr29 = 0, $12 = 0;
+ var $info_ptr30 = 0, $13 = 0, $call31 = 0, $14 = 0, $call32 = 0, $15 = 0, $call33 = 0, $16 = 0, $17$0 = 0, $17$1 = 0, $18 = 0, $19 = 0, $20 = 0, $call34 = 0, $21 = 0, $row_pointers35 = 0, $22 = 0, $23 = 0, $cmp36 = 0, $24 = 0;
+ var $25 = 0, $26 = 0, $mul = 0, $add_ptr = 0, $27 = 0, $row_pointers37 = 0, $28 = 0, $arrayidx = 0, $29 = 0, $inc = 0, $png_ptr38 = 0, $30 = 0, $row_pointers39 = 0, $31 = 0, $32 = 0, $png_ptr40 = 0, $33 = 0, $info_ptr41 = 0, $34 = 0, $call42 = 0;
+ var $35 = 0, $png_ptr43 = 0, $36 = 0, $info_ptr44 = 0, $37 = 0, $call45 = 0, $state46 = 0, $png_ptr47 = 0, $38 = 0, $end_info48 = 0, $39 = 0, $end_info49 = 0, $40 = 0, $41 = 0, $readTexts = 0, $42 = 0, $call51 = 0, $sub = 0, $cmp52 = 0, $43 = 0;
+ var $readTexts54 = 0, $44 = 0, $45 = 0, $call55 = 0, $readTexts56 = 0, $46 = 0, $47 = 0, $add = 0, $call57 = 0, $48 = 0, $add59 = 0, $png_ptr61 = 0, $info_ptr62 = 0, $end_info63 = 0, $row_pointers64 = 0, $49 = 0, $isnull65 = 0, $50 = 0, $png_ptr68 = 0, $state69 = 0;
+ var $51 = 0, $cmp70 = 0, $52 = 0, $call72 = 0, $cmp73 = 0, $53 = 0, $call75 = 0, $54 = 0, $55 = 0, $cmp78 = 0, $56 = 0, $57 = 0, $58 = 0, $mul80 = 0, $add_ptr81 = 0, $59 = 0, $60 = 0, $add_ptr82 = 0, $61 = 0, $62 = 0;
+ var $cmp83 = 0, $63 = 0, $64 = 0, $conv = 0, $65 = 0, $cmp84 = 0, $66 = 0, $67 = 0, $incdec_ptr = 0, $68 = 0, $inc88 = 0, $69 = 0, label = 0, setjmpLabel = 0, setjmpTable = 0;
+ var sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 1;
+ setjmpLabel = 0;
+ setjmpTable = STACKTOP;
+ STACKTOP = STACKTOP + 168 | 0;
+ HEAP32[setjmpTable >> 2] = 0;
+ while (1) switch (label | 0) {
+ case 1:
+ $width = sp | 0;
+ $height = sp + 8 | 0;
+ $bit_depth = sp + 16 | 0;
+ $color_type = sp + 24 | 0;
+ $this_addr = $this;
+ $outImage_addr = $outImage;
+ $this1 = $this_addr;
+ $state = $this1 + 32 | 0;
+ $0 = HEAP32[$state >> 2] | 0;
+ $cmp = ($0 | 0) == 3;
+ if ($cmp) {
+ label = 2;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 2:
+ $retval = 0;
+ label = 37;
+ break;
+ case 3:
+ $state2 = $this1 + 32 | 0;
+ $1 = HEAP32[$state2 >> 2] | 0;
+ $cmp3 = ($1 | 0) == 0;
+ if ($cmp3) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $call = invoke_ii(900, $this1 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ($call) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $state5 = $this1 + 32 | 0;
+ HEAP32[$state5 >> 2] = 3;
+ $retval = 0;
+ label = 37;
+ break;
+ case 6:
+ $row_pointers = $this1 + 28 | 0;
+ HEAP32[$row_pointers >> 2] = 0;
+ $png_ptr = $this1 + 16 | 0;
+ $2 = HEAP32[$png_ptr >> 2] | 0;
+ $call7 = invoke_iiii(30, $2 | 0, 2638 | 0, 156 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $arraydecay = $call7 | 0;
+ $call8 = _saveSetjmp($arraydecay | 0, label, setjmpTable) | 0;
+ label = 38;
+ break;
+ case 38:
+ $tobool = ($call8 | 0) != 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 7:
+ $png_ptr10 = $this1 + 16 | 0;
+ $info_ptr = $this1 + 20 | 0;
+ $end_info = $this1 + 24 | 0;
+ invoke_viii(640, $png_ptr10 | 0, $info_ptr | 0, $end_info | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $row_pointers11 = $this1 + 28 | 0;
+ $3 = HEAP32[$row_pointers11 >> 2] | 0;
+ $isnull = ($3 | 0) == 0;
+ if ($isnull) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $4 = $3;
+ invoke_vi(926, $4 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 9;
+ break;
+ case 9:
+ $png_ptr12 = $this1 + 16 | 0;
+ HEAP32[$png_ptr12 >> 2] = 0;
+ $state13 = $this1 + 32 | 0;
+ HEAP32[$state13 >> 2] = 3;
+ $retval = 0;
+ label = 37;
+ break;
+ case 10:
+ $5 = $outImage_addr;
+ $png_ptr15 = $this1 + 16 | 0;
+ $6 = HEAP32[$png_ptr15 >> 2] | 0;
+ $info_ptr16 = $this1 + 20 | 0;
+ $7 = HEAP32[$info_ptr16 >> 2] | 0;
+ $gamma = $this1 | 0;
+ $8 = +HEAPF32[$gamma >> 2];
+ invoke_viiif(2, $5 | 0, $6 | 0, $7 | 0, +$8);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $9 = $outImage_addr;
+ $call17 = invoke_ii(832, $9 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ if ($call17) {
+ label = 11;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 11:
+ $png_ptr19 = $this1 + 16 | 0;
+ $info_ptr20 = $this1 + 20 | 0;
+ $end_info21 = $this1 + 24 | 0;
+ invoke_viii(640, $png_ptr19 | 0, $info_ptr20 | 0, $end_info21 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $row_pointers22 = $this1 + 28 | 0;
+ $10 = HEAP32[$row_pointers22 >> 2] | 0;
+ $isnull23 = ($10 | 0) == 0;
+ if ($isnull23) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $11 = $10;
+ invoke_vi(926, $11 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 13;
+ break;
+ case 13:
+ $png_ptr26 = $this1 + 16 | 0;
+ HEAP32[$png_ptr26 >> 2] = 0;
+ $state27 = $this1 + 32 | 0;
+ HEAP32[$state27 >> 2] = 3;
+ $retval = 0;
+ label = 37;
+ break;
+ case 14:
+ $png_ptr29 = $this1 + 16 | 0;
+ $12 = HEAP32[$png_ptr29 >> 2] | 0;
+ $info_ptr30 = $this1 + 20 | 0;
+ $13 = HEAP32[$info_ptr30 >> 2] | 0;
+ $call31 = invoke_iiiiiiiiii(2, $12 | 0, $13 | 0, $width | 0, $height | 0, $bit_depth | 0, $color_type | 0, 0 | 0, 0 | 0, 0 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $14 = $outImage_addr;
+ $call32 = invoke_ii(850, $14 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $data = $call32;
+ $15 = $outImage_addr;
+ $call33 = invoke_ii(284, $15 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $bpl = $call33;
+ $16 = HEAP32[$height >> 2] | 0;
+ $17$0 = invoke_iii(860, $16 | 0, 4 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $17$1 = tempRet0;
+ $18 = $17$1;
+ $19 = $17$0;
+ $20 = $18 ? -1 : $19;
+ $call34 = invoke_ii(550, $20 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $21 = $call34;
+ $row_pointers35 = $this1 + 28 | 0;
+ HEAP32[$row_pointers35 >> 2] = $21;
+ $y = 0;
+ label = 15;
+ break;
+ case 15:
+ $22 = $y;
+ $23 = HEAP32[$height >> 2] | 0;
+ $cmp36 = $22 >>> 0 < $23 >>> 0;
+ if ($cmp36) {
+ label = 16;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 16:
+ $24 = $data;
+ $25 = $y;
+ $26 = $bpl;
+ $mul = Math_imul($25, $26) | 0;
+ $add_ptr = $24 + $mul | 0;
+ $27 = $y;
+ $row_pointers37 = $this1 + 28 | 0;
+ $28 = HEAP32[$row_pointers37 >> 2] | 0;
+ $arrayidx = $28 + ($27 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $add_ptr;
+ label = 17;
+ break;
+ case 17:
+ $29 = $y;
+ $inc = $29 + 1 | 0;
+ $y = $inc;
+ label = 15;
+ break;
+ case 18:
+ $png_ptr38 = $this1 + 16 | 0;
+ $30 = HEAP32[$png_ptr38 >> 2] | 0;
+ $row_pointers39 = $this1 + 28 | 0;
+ $31 = HEAP32[$row_pointers39 >> 2] | 0;
+ invoke_vii(858, $30 | 0, $31 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $32 = $outImage_addr;
+ $png_ptr40 = $this1 + 16 | 0;
+ $33 = HEAP32[$png_ptr40 >> 2] | 0;
+ $info_ptr41 = $this1 + 20 | 0;
+ $34 = HEAP32[$info_ptr41 >> 2] | 0;
+ $call42 = invoke_iii(690, $33 | 0, $34 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ invoke_vii(1890, $32 | 0, $call42 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $35 = $outImage_addr;
+ $png_ptr43 = $this1 + 16 | 0;
+ $36 = HEAP32[$png_ptr43 >> 2] | 0;
+ $info_ptr44 = $this1 + 20 | 0;
+ $37 = HEAP32[$info_ptr44 >> 2] | 0;
+ $call45 = invoke_iii(256, $36 | 0, $37 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ invoke_vii(2126, $35 | 0, $call45 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $state46 = $this1 + 32 | 0;
+ HEAP32[$state46 >> 2] = 2;
+ $png_ptr47 = $this1 + 16 | 0;
+ $38 = HEAP32[$png_ptr47 >> 2] | 0;
+ $end_info48 = $this1 + 24 | 0;
+ $39 = HEAP32[$end_info48 >> 2] | 0;
+ invoke_vii(36, $38 | 0, $39 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $end_info49 = $this1 + 24 | 0;
+ $40 = HEAP32[$end_info49 >> 2] | 0;
+ invoke_vii(2752, $this1 | 0, $40 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $i = 0;
+ label = 19;
+ break;
+ case 19:
+ $41 = $i;
+ $readTexts = $this1 + 12 | 0;
+ $42 = $readTexts;
+ $call51 = invoke_ii(618, $42 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $sub = $call51 - 1 | 0;
+ $cmp52 = ($41 | 0) < ($sub | 0);
+ if ($cmp52) {
+ label = 20;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 20:
+ $43 = $outImage_addr;
+ $readTexts54 = $this1 + 12 | 0;
+ $44 = $readTexts54;
+ $45 = $i;
+ $call55 = invoke_iii(502, $44 | 0, $45 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $readTexts56 = $this1 + 12 | 0;
+ $46 = $readTexts56;
+ $47 = $i;
+ $add = $47 + 1 | 0;
+ $call57 = invoke_iii(502, $46 | 0, $add | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ invoke_viii(550, $43 | 0, $call55 | 0, $call57 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 21;
+ break;
+ case 21:
+ $48 = $i;
+ $add59 = $48 + 2 | 0;
+ $i = $add59;
+ label = 19;
+ break;
+ case 22:
+ $png_ptr61 = $this1 + 16 | 0;
+ $info_ptr62 = $this1 + 20 | 0;
+ $end_info63 = $this1 + 24 | 0;
+ invoke_viii(640, $png_ptr61 | 0, $info_ptr62 | 0, $end_info63 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $row_pointers64 = $this1 + 28 | 0;
+ $49 = HEAP32[$row_pointers64 >> 2] | 0;
+ $isnull65 = ($49 | 0) == 0;
+ if ($isnull65) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $50 = $49;
+ invoke_vi(926, $50 | 0);
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ label = 24;
+ break;
+ case 24:
+ $png_ptr68 = $this1 + 16 | 0;
+ HEAP32[$png_ptr68 >> 2] = 0;
+ $state69 = $this1 + 32 | 0;
+ HEAP32[$state69 >> 2] = 0;
+ $51 = HEAP32[$color_type >> 2] | 0;
+ $cmp70 = ($51 | 0) == 3;
+ if ($cmp70) {
+ label = 25;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 25:
+ $52 = $outImage_addr;
+ $call72 = invoke_ii(926, $52 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $cmp73 = ($call72 | 0) == 3;
+ if ($cmp73) {
+ label = 26;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 26:
+ $53 = $outImage_addr;
+ $call75 = invoke_ii(860, $53 | 0) | 0;
+ if ((__THREW__ | 0) != 0 & (threwValue | 0) != 0) {
+ setjmpLabel = _testSetjmp(HEAP32[__THREW__ >> 2] | 0, setjmpTable) | 0;
+ if ((setjmpLabel | 0) > 0) {
+ label = -1;
+ break;
+ } else return 0 | 0;
+ }
+ __THREW__ = threwValue = 0;
+ $color_table_size = $call75;
+ $y76 = 0;
+ label = 27;
+ break;
+ case 27:
+ $54 = $y76;
+ $55 = HEAP32[$height >> 2] | 0;
+ $cmp78 = ($54 | 0) < ($55 | 0);
+ if ($cmp78) {
+ label = 28;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 28:
+ $56 = $data;
+ $57 = $y76;
+ $58 = $bpl;
+ $mul80 = Math_imul($57, $58) | 0;
+ $add_ptr81 = $56 + $mul80 | 0;
+ $p = $add_ptr81;
+ $59 = $p;
+ $60 = HEAP32[$width >> 2] | 0;
+ $add_ptr82 = $59 + $60 | 0;
+ $end = $add_ptr82;
+ label = 29;
+ break;
+ case 29:
+ $61 = $p;
+ $62 = $end;
+ $cmp83 = $61 >>> 0 < $62 >>> 0;
+ if ($cmp83) {
+ label = 30;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 30:
+ $63 = $p;
+ $64 = HEAP8[$63] | 0;
+ $conv = $64 & 255;
+ $65 = $color_table_size;
+ $cmp84 = ($conv | 0) >= ($65 | 0);
+ if ($cmp84) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ $66 = $p;
+ HEAP8[$66] = 0;
+ label = 32;
+ break;
+ case 32:
+ $67 = $p;
+ $incdec_ptr = $67 + 1 | 0;
+ $p = $incdec_ptr;
+ label = 29;
+ break;
+ case 33:
+ label = 34;
+ break;
+ case 34:
+ $68 = $y76;
+ $inc88 = $68 + 1 | 0;
+ $y76 = $inc88;
+ label = 27;
+ break;
+ case 35:
+ label = 36;
+ break;
+ case 36:
+ $retval = 1;
+ label = 37;
+ break;
+ case 37:
+ $69 = $retval;
+ STACKTOP = sp;
+ return $69 | 0;
+ case -1:
+ if ((setjmpLabel | 0) == 6) {
+ $call8 = threwValue;
+ label = 38;
+ }
+ __THREW__ = threwValue = 0;
+ break;
+ }
+ return 0;
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "looop8", "multiloop", "multiloop2", "tempDouble2", "watIf", "select2", "binary", "cute"]
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 3a6d70bc..fa59dbec 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -1773,9 +1773,7 @@ function ensureMinifiedNames(n) { // make sure the nth index in minifiedNames ex
}
}
-// Very simple 'registerization', coalescing of variables into a smaller number,
-// as part of minification. Globals-level minification began in a previous pass,
-// we receive extraInfo which tells us how to rename globals. (Only in asm.js.)
+// Very simple 'registerization', coalescing of variables into a smaller number.
//
// We do not optimize when there are switches, so this pass only makes sense with
// relooping.
@@ -1811,6 +1809,7 @@ function registerize(ast) {
// Replace all var definitions with assignments; we will add var definitions at the top after we registerize
// We also mark local variables - i.e., having a var definition
var localVars = {};
+ var allVars = {};
var hasSwitch = false; // we cannot optimize variables if there is a switch, unless in asm mode
traverse(fun, function(node, type) {
if (type === 'var') {
@@ -1823,74 +1822,25 @@ function registerize(ast) {
}
} else if (type === 'switch') {
hasSwitch = true;
+ } else if (type === 'name') {
+ allVars[node[1]] = 1;
}
});
vacuum(fun);
- if (extraInfo && extraInfo.globals) {
- assert(asm);
- var usedGlobals = {};
- var nextLocal = 0;
- // Minify globals using the mapping we were given
- traverse(fun, function(node, type) {
- if (type === 'name') {
- var name = node[1];
- var minified = extraInfo.globals[name];
- if (minified) {
- assert(!localVars[name], name); // locals must not shadow globals, or else we don't know which is which
- if (localVars[minified]) {
- // trying to minify a global into a name used locally. rename all the locals
- var newName = '$_newLocal_' + (nextLocal++);
- assert(!localVars[newName]);
- if (params[minified]) {
- params[newName] = 1;
- delete params[minified];
- }
- localVars[newName] = 1;
- delete localVars[minified];
- asmData.vars[newName] = asmData.vars[minified];
- delete asmData.vars[minified];
- asmData.params[newName] = asmData.params[minified];
- delete asmData.params[minified];
- traverse(fun, function(node, type) {
- if (type === 'name' && node[1] === minified) {
- node[1] = newName;
- }
- });
- if (fun[2]) {
- for (var i = 0; i < fun[2].length; i++) {
- if (fun[2][i] === minified) fun[2][i] = newName;
- }
- }
- }
- node[1] = minified;
- usedGlobals[minified] = 1;
- }
- }
- });
- if (fun[1] in extraInfo.globals) { // if fun was created by a previous optimization pass, it will not be here
- fun[1] = extraInfo.globals[fun[1]];
- assert(fun[1]);
- }
- var nextRegName = 0;
- }
var regTypes = {};
function getNewRegName(num, name) {
- if (!asm) return 'r' + num;
- var type = asmData.vars[name];
- if (!extraInfo || !extraInfo.globals) {
- var ret = (type ? 'd' : 'i') + num;
+ var ret;
+ if (!asm) {
+ ret = 'r' + num;
+ } else {
+ var type = asmData.vars[name];
+ ret = (type ? 'd' : 'i') + num;
regTypes[ret] = type;
- return ret;
}
- // find the next free minified name that is not used by a global that shows up in this function
- while (1) {
- ensureMinifiedNames(nextRegName);
- var ret = minifiedNames[nextRegName++];
- if (!usedGlobals[ret]) {
- regTypes[ret] = type;
- return ret;
- }
+ if (ret in allVars) {
+ assert(ret in localVars, 'register shadows non-local name');
}
+ return ret;
}
// Find the # of uses of each variable.
// While doing so, check if all a variable's uses are dominated in a simple
@@ -2111,33 +2061,6 @@ function registerize(ast) {
}
}
denormalizeAsm(fun, finalAsmData);
- if (extraInfo && extraInfo.globals) {
- // minify in asm var definitions, that denormalizeAsm just generated
- function minify(value) {
- if (value && value[0] === 'call' && value[1][0] === 'name') {
- var name = value[1][1];
- var minified = extraInfo.globals[name];
- if (minified) {
- value[1][1] = minified;
- }
- }
- }
- var stats = fun[3];
- for (var i = 0; i < stats.length; i++) {
- var line = stats[i];
- if (i >= fun[2].length && line[0] !== 'var') break; // when we pass the arg and var coercions, break
- if (line[0] === 'stat') {
- assert(line[1][0] === 'assign');
- minify(line[1][3]);
- } else {
- assert(line[0] === 'var');
- var pairs = line[1];
- for (var j = 0; j < pairs.length; j++) {
- minify(pairs[j][1]);
- }
- }
- }
- }
}
});
}
@@ -2322,7 +2245,7 @@ function eliminate(ast, memSafe) {
var memoryInvalidated = false;
var callsInvalidated = false;
function track(name, value, defNode) { // add a potential that has just been defined to the tracked list, we hope to eliminate it
- var usesGlobals = false, usesMemory = false, deps = {}, doesCall = false;
+ var usesGlobals = false, usesMemory = false, deps = {}, doesCall = false, hasDeps = false;
var ignoreName = false; // one-time ignorings of names, as first op in sub and call
traverse(value, function(node, type) {
if (type === 'name') {
@@ -2333,6 +2256,7 @@ function eliminate(ast, memSafe) {
}
if (!(name in potentials)) { // deps do not matter for potentials - they are defined once, so no complexity
deps[name] = 1;
+ hasDeps = true;
}
} else {
ignoreName = false;
@@ -2354,6 +2278,7 @@ function eliminate(ast, memSafe) {
usesMemory: usesMemory,
defNode: defNode,
deps: deps,
+ hasDeps: hasDeps,
doesCall: doesCall
};
globalsInvalidated = false;
@@ -2426,7 +2351,7 @@ function eliminate(ast, memSafe) {
function traverseInOrder(node, ignoreSub, ignoreName) {
if (abort) return;
//nesting++; // printErr-related
- //printErr(spaces(2*(nesting+1)) + 'trav: ' + JSON.stringify(node).substr(0, 50) + ' : ' + keys(tracked) + ' : ' + [allowTracking, ignoreSub, ignoreName]);
+ //printErr(JSON.stringify(node).substr(0, 50) + ' : ' + keys(tracked) + ' : ' + [allowTracking, ignoreSub, ignoreName]);
var type = node[0];
if (type === 'assign') {
var target = node[2];
@@ -2602,6 +2527,8 @@ function eliminate(ast, memSafe) {
traverseInOrder(node[3]);
} else if (type === 'switch') {
traverseInOrder(node[1]);
+ var originalTracked = {};
+ for (var o in tracked) originalTracked[o] = 1;
var cases = node[2];
for (var i = 0; i < cases.length; i++) {
var c = cases[i];
@@ -2610,6 +2537,15 @@ function eliminate(ast, memSafe) {
for (var j = 0; j < stats.length; j++) {
traverseInOrder(stats[j]);
}
+ // We cannot track from one switch case into another, undo all new trackings TODO: general framework here, use in if-else as well
+ for (var t in tracked) {
+ if (!(t in originalTracked)) {
+ var info = tracked[t];
+ if (info.usesGlobals || info.usesMemory || info.hasDeps) {
+ delete tracked[t];
+ }
+ }
+ }
}
} else {
if (!(type in ABORTING_ELIMINATOR_SCAN_NODES)) {
@@ -2900,6 +2836,92 @@ function minifyGlobals(ast) {
suffix = '// EXTRA_INFO:' + JSON.stringify(minified);
}
+
+function minifyLocals(ast) {
+ assert(asm)
+ assert(extraInfo && extraInfo.globals)
+
+ traverseGeneratedFunctions(ast, function(fun, type) {
+
+ // Analyse the asmjs to figure out local variable names,
+ // but operate on the original source tree so that we don't
+ // miss any global names in e.g. variable initializers.
+ var asmData = normalizeAsm(fun); denormalizeAsm(fun, asmData); // TODO: we can avoid modifying at all here - we just need a list of local vars+params
+ var newNames = {};
+ var usedNames = {};
+
+ // Find all the globals that we need to minify using
+ // pre-assigned names. Don't actually minify them yet
+ // as that might interfere with local variable names.
+ function isLocalName(name) {
+ return name in asmData.vars || name in asmData.params;
+ }
+ traverse(fun, function(node, type) {
+ if (type === 'name') {
+ var name = node[1];
+ if (!isLocalName(name)) {
+ var minified = extraInfo.globals[name];
+ if (minified){
+ newNames[name] = minified;
+ usedNames[minified] = 1;
+ }
+ }
+ }
+ });
+
+ // Traverse and minify all names.
+ // The first time we encounter a local name, we assign it a
+ // minified name that's not currently in use. Allocating on
+ // demand means they're processed in a predicatable order,
+ // which is very handy for testing/debugging purposes.
+ var nextMinifiedName = 0;
+ function getNextMinifiedName() {
+ var minified;
+ while (1) {
+ ensureMinifiedNames(nextMinifiedName);
+ minified = minifiedNames[nextMinifiedName++];
+ // TODO: we can probably remove !isLocalName here
+ if (!usedNames[minified] && !isLocalName(minified)) {
+ return minified;
+ }
+ }
+ }
+ if (fun[1] in extraInfo.globals) {
+ fun[1] = extraInfo.globals[fun[1]];
+ assert(fun[1]);
+ }
+ if (fun[2]) {
+ for (var i = 0; i < fun[2].length; i++) {
+ var minified = getNextMinifiedName();
+ newNames[fun[2][i]] = minified;
+ fun[2][i] = minified;
+ }
+ }
+ traverse(fun[3], function(node, type) {
+ if (type === 'name') {
+ var name = node[1];
+ var minified = newNames[name];
+ if (minified) {
+ node[1] = minified;
+ } else if (isLocalName(name)) {
+ minified = getNextMinifiedName();
+ newNames[name] = minified;
+ node[1] = minified;
+ }
+ } else if (type === 'var') {
+ node[1].forEach(function(defn) {
+ var name = defn[0];
+ if (!(name in newNames)) {
+ newNames[name] = getNextMinifiedName();
+ }
+ defn[0] = newNames[name];
+ });
+ }
+ });
+
+ });
+}
+
// Relocation pass for a shared module (for the functions part of the module)
//
// 1. Replace function names with alternate names as defined (to avoid colliding with
@@ -3866,6 +3888,104 @@ function outline(ast) {
});
}
+function safeHeap(ast) {
+ function fixPtr(ptr, heap) {
+ switch (heap) {
+ case 'HEAP8': case 'HEAPU8': break;
+ case 'HEAP16': case 'HEAPU16': {
+ if (ptr[0] === 'binary') {
+ assert(ptr[1] === '>>' && ptr[3][0] === 'num' && ptr[3][1] === 1);
+ ptr = ptr[2]; // skip the shift
+ } else {
+ ptr = ['binary', '*', ptr, ['num', 2]]; // was unshifted, convert to absolute address
+ }
+ break;
+ }
+ case 'HEAP32': case 'HEAPU32': {
+ if (ptr[0] === 'binary') {
+ assert(ptr[1] === '>>' && ptr[3][0] === 'num' && ptr[3][1] === 2);
+ ptr = ptr[2]; // skip the shift
+ } else {
+ ptr = ['binary', '*', ptr, ['num', 4]]; // was unshifted, convert to absolute address
+ }
+ break;
+ }
+ case 'HEAPF32': {
+ if (ptr[0] === 'binary') {
+ assert(ptr[1] === '>>' && ptr[3][0] === 'num' && ptr[3][1] === 2);
+ ptr = ptr[2]; // skip the shift
+ } else {
+ ptr = ['binary', '*', ptr, ['num', 4]]; // was unshifted, convert to absolute address
+ }
+ break;
+ }
+ case 'HEAPF64': {
+ if (ptr[0] === 'binary') {
+ assert(ptr[1] === '>>' && ptr[3][0] === 'num' && ptr[3][1] === 3);
+ ptr = ptr[2]; // skip the shift
+ } else {
+ ptr = ['binary', '*', ptr, ['num', 8]]; // was unshifted, convert to absolute address
+ }
+ break;
+ }
+ default: throw 'bad heap ' + heap;
+ }
+ ptr = ['binary', '|', ptr, ['num', 0]];
+ return ptr;
+ }
+ traverseGenerated(ast, function(node, type) {
+ if (type === 'assign') {
+ if (node[1] === true && node[2][0] === 'sub') {
+ var heap = node[2][1][1];
+ var ptr = fixPtr(node[2][2], heap);
+ var value = node[3];
+ // SAFE_HEAP_STORE(ptr, value, bytes, isFloat)
+ switch (heap) {
+ case 'HEAP8': case 'HEAPU8': {
+ return ['call', ['name', 'SAFE_HEAP_STORE'], [ptr, makeAsmCoercion(value, ASM_INT), ['num', 1], ['num', '0']]];
+ }
+ case 'HEAP16': case 'HEAPU16': {
+ return ['call', ['name', 'SAFE_HEAP_STORE'], [ptr, makeAsmCoercion(value, ASM_INT), ['num', 2], ['num', '0']]];
+ }
+ case 'HEAP32': case 'HEAPU32': {
+ return ['call', ['name', 'SAFE_HEAP_STORE'], [ptr, makeAsmCoercion(value, ASM_INT), ['num', 4], ['num', '0']]];
+ }
+ case 'HEAPF32': {
+ return ['call', ['name', 'SAFE_HEAP_STORE'], [ptr, makeAsmCoercion(value, ASM_FLOAT), ['num', 4], ['num', '1']]];
+ }
+ case 'HEAPF64': {
+ return ['call', ['name', 'SAFE_HEAP_STORE'], [ptr, makeAsmCoercion(value, ASM_DOUBLE), ['num', 8], ['num', '1']]];
+ }
+ default: throw 'bad heap ' + heap;
+ }
+ }
+ } else if (type === 'sub') {
+ var heap = node[1][1];
+ if (heap[0] !== 'H') return;
+ var ptr = fixPtr(node[2], heap);
+ // SAFE_HEAP_LOAD(ptr, bytes, isFloat)
+ switch (heap) {
+ case 'HEAP8': case 'HEAPU8': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0']]], ASM_INT);
+ }
+ case 'HEAP16': case 'HEAPU16': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0']]], ASM_INT);
+ }
+ case 'HEAP32': case 'HEAPU32': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0']]], ASM_INT);
+ }
+ case 'HEAPF32': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '1']]], ASM_FLOAT);
+ }
+ case 'HEAPF64': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 8], ['num', '1']]], ASM_DOUBLE);
+ }
+ default: throw 'bad heap ' + heap;
+ }
+ }
+ });
+}
+
// 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)
@@ -3956,6 +4076,7 @@ function asmLastOpts(ast) {
var minifyWhitespace = false, printMetadata = true, asm = false, last = false;
var passes = {
+ // passes
dumpAst: dumpAst,
dumpSrc: dumpSrc,
unGlobalize: unGlobalize,
@@ -3971,8 +4092,12 @@ var passes = {
eliminateMemSafe: eliminateMemSafe,
aggressiveVariableElimination: aggressiveVariableElimination,
minifyGlobals: minifyGlobals,
+ minifyLocals: minifyLocals,
relocate: relocate,
outline: outline,
+ safeHeap: safeHeap,
+
+ // flags
minifyWhitespace: function() { minifyWhitespace = true },
noPrintMetadata: function() { printMetadata = false },
asm: function() { asm = true },
diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py
index 71b6f377..e030b707 100644
--- a/tools/js_optimizer.py
+++ b/tools/js_optimizer.py
@@ -26,7 +26,7 @@ class Minifier:
'''
asm.js minification support. We calculate minification of
globals here, then pass that into the parallel js-optimizer.js runners which
- during registerize perform minification of locals.
+ perform minification of locals.
'''
def __init__(self, js, js_engine):
@@ -117,9 +117,9 @@ def run_on_js(filename, passes, js_engine, jcache, source_map=False, extra_info=
know_generated = suffix or start_funcs >= 0
- minify_globals = 'registerizeAndMinify' in passes and 'asm' in passes
+ minify_globals = 'minifyNames' in passes and 'asm' in passes
if minify_globals:
- passes = map(lambda p: p if p != 'registerizeAndMinify' else 'registerize', passes)
+ passes = map(lambda p: p if p != 'minifyNames' else 'minifyLocals', passes)
start_asm = js.find(start_asm_marker)
end_asm = js.rfind(end_asm_marker)
assert (start_asm >= 0) == (end_asm >= 0)
diff --git a/tools/shared.py b/tools/shared.py
index 2ae37f91..1ee5cce8 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -345,7 +345,7 @@ def find_temp_directory():
# we re-check sanity when the settings are changed)
# We also re-check sanity and clear the cache when the version changes
-EMSCRIPTEN_VERSION = '1.9.0'
+EMSCRIPTEN_VERSION = '1.9.2'
def generate_sanity():
return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT + '|' + get_clang_version()